is it possible to use map with 2 operators in it like map ((*2)+3) [1,2,3,4]? If is yes how? i want to make a function that apply (x*2)+3 on a list.
You map a single function. But that function can do whatever you want. Your example can be given as an anonymous function for example:
map (\n -> n * 2 + 3) [1,2,3,4]
But you can also use function composition, which is likely more readable for a case like this where your function is a case of "do one thing, then the other":
map ((+3) . (*2)) [1,2,3,4]
This in turn is equal (by the so-called "functor laws") to
map (+3) . map (*2) $ [1,2,3,4]
Which I personally find a little more readable.
I think it is easy to first introduce a lambda expression here:
map (\x -> (x*2)+3) [1,2,3,4]
This will do exactly what you want. You can perform "function composition" with the (.) :: (b -> c) -> (a -> b) -> a -> c function, and thus write this as:
map ((+3) . (*2)) [1,2,3,4]
Here you thus can see it as a "chain" of functions, where we pass the input to the rightmost function (here (*2)), and then the result is passed to the leftmost function (here (+3)).
Related
I am a bit surprised that this was not asked before. Maybe it is a stupid question.
I know that flip is changing the order of two arguments.
Example:
(-) 5 3
= 5 - 3
= 2
flip (-) 5 3
= 3 - 5
= -2
But why would I need such a function? Why not just change the inputs manually?
Why not just write:
(-) 3 5
= 3 - 5
= -2
One is unlikely to ever use the flip function on a function that is immediately applied to two or more arguments, but flip can be useful in two situations:
If the function is passed higher-order to a different function, one cannot simply reverse the arguments at the call site, since the call site is in another function! For example, these two expressions produce very different results:
ghci> foldl (-) 0 [1, 2, 3, 4]
-10
ghci> foldl (flip (-)) 0 [1, 2, 3, 4]
2
In this case, we cannot swap the arguments of (-) because we do not apply (-) directly; foldl applies it for us. So we can use flip (-) instead of writing out the whole lambda \x y -> y - x.
Additionally, it can be useful to use flip to partially apply a function to its second argument. For example, we could use flip to write a function that builds an infinite list using a builder function that is provided the element’s index in the list:
buildList :: (Integer -> a) -> [a]
buildList = flip map [0..]
ghci> take 10 (buildList (\x -> x * x))
[0,1,4,9,16,25,36,49,64,81]
Perhaps more frequently, this is used when we want to partially apply the second argument of a function that will be used higher-order, like in the first example:
ghci> map (flip map [1, 2, 3]) [(+ 1), (* 2)]
[[2,3,4],[2,4,6]]
Sometimes, instead of using flip in a case like this, people will use infix syntax instead, since operator sections have the unique property that they can supply the first or second argument to a function. Therefore, writing (`f` x) is equivalent to writing flip f x. Personally, I think writing flip directly is usually easier to read, but that’s a matter of taste.
One very useful example of flip usage is sorting in descending order. You can see how it works in ghci:
ghci> import Data.List
ghci> :t sortBy
sortBy :: (a -> a -> Ordering) -> [a] -> [a]
ghci> :t compare
compare :: Ord a => a -> a -> Ordering
ghci> sortBy compare [2,1,3]
[1,2,3]
ghci> sortBy (flip compare) [2,1,3]
[3,2,1]
Sometimes you'll want to use a function by supplying the second parameter but take it's first parameter from somewhere else. For example:
map (flip (-) 5) [1..5]
Though this can also be written as:
map (\x -> x - 5) [1..5]
Another use case is when the second argument is long:
flip (-) 5 $
if odd x
then x + 1
else x
But you can always use a let expression to name the first parameter computation and then not use flip.
I’m trying to use the find function on a list of pairs, and I want to find the first pair in which the first element equals x, so I wrote:
find (x == fst) list
Since the fst function lacks an argument, I thought (x == fst) would be a function that takes in a tuple and returns a boolean, but the compiler interprets it as a boolean, as if fst were a variable. Maybe fst is being interpreted as a function? But doesn’t that require it to be surrounded by ()?
I did solve the problem using a list comprehension instead but I’m still curious as how to one would solve it using find.
(==) has type x -> x -> Bool. In your case, type x is (a, b) -> a. This is because one of it's operands is fst, which has that type. Therefore, the type of (==) in your case is ((a, b) -> a) -> ((a, b) -> a) -> Bool. That is, (==) is a function that compares two functions, x and fst.
What you want is to compose fst and (==). For example, (\y -> (x == fst y). This is a function that takes a tuple, y, and checks if x is equal to its first value.
There is a function that composes functions for you, (.). It takes two functions, f(x) and g(x), and returns another function, f(g(x)). You can use this function for your program like this: find ((x ==) . fst) list.
Compare the following programs, the first written as a lambda function, the second with the function composition operator:
(\y -> (x == fst y)
-- Compared to:
(x ==) . fst
Summary:
(==) is comparing two functions, x and fst, and returning a Bool.
What you want instead is a function that takes in a tuple, gets the first item from it, and compares it to x. This can be done with function composition.
If you want to pass a variable into a particular position, use a lambda function:
(\ y -> x == fst y)
Otherwise the compiler has no idea exactly where you're hoping to insert a variable.
If your function calls one function, you can use currying to take a short cut. But for complex expressions, that doesn't work. You can't just leave off the last term in an expression and expect it to work. It only works for a single function.
The other alternative is to take the function (x ==) and the function fst and chain them with the (.) operator:
((x ==) . fst)
It's a matter of personal taste which is "better". (There is no performance difference; the only difference is what your source code looks like.)
I want to write an expression which will give a list that is equal to the list comprehension [x|x<-[1..100], x`mod`7==0], but I'm asked by my teacher to use $ in this program.
So, how could I use $ in here?
PS: I'm new to Haskell, so would prefer easy expressions, please.
($) is in an infix operator with a type signature
($) :: (a -> b) -> a -> b
which means it takes two parameters, first a function (a -> b) (on the left) which accepts a single parameter, a value of type designated by the type variable a. The second parameter of ($) (on the right) is a single value again designated by the type variable a. Then the ($) operator simply applies it's second parameter to the first parameter. So for an example (+2) $ 3 would give us 5.
So if you insist on doing list comprehensions you may do as follows in point-free style;
Prelude> [x|x<-[1..100], (== 0) . mod x $ 7]
[7,14,21,28,35,42,49,56,63,70,77,84,91,98]
or in a more straightforward fashion
Prelude> filter ((==0) . (`mod` 7)) $ take 100 [1..]
[7,14,21,28,35,42,49,56,63,70,77,84,91,98]
$ just means "take whatever is on the right, and pass it as argument to the left".
So for example :
map (`mod`7) (take 100 [1..])
map (`mod`7) $ take 100 [1..]
Those two lines are the same, the $ just means you can avoid the parenthesis around the second call.
The take is useless but I didn't have a better idea for a simple example :)
I just want to know how do we know which functions need brackets () and which ones do not? For example
replicate 100 (product (map (*3) (zipWith max [1,2,3,4,5] [4,5,6,7,8])))
works fine. But
replicate 100 (product (map (*3) (zipWith (max [1,2,3,4,5] [4,5,6,7,8]))))
does not work. It is because I put a set of brackets for zipWith. In this small example, zipWith and max do not have brackets, but replicate, product and map do. In general is there a way to know/figure out which functions need brackets and which ones dont.
Function application is left associative. So, when you write an expression like:
f g h x
it means:
((f g) h) x
And also the type of zipWith provides a clue:
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
it says that zipWith has 3 parameters: a function and two lists.
When you write:
zipWith (max [1,2,3,4,5] [4,5,6,7,8])
The interpreter will understand that
max [1,2,3,4,5] [4,5,6,7,8]
will be the first parameter to zipWith, which is type incorrect. Note that zipWith expects a function of two arguments as its first argument and, as pointed out by #Cubic, max [1,2,3,4,5] [4,5,6,7,8] will return the maximum
between these two lists according the usual lexicographic order, which will be of type [a], for some type a which is instance of Ord and Num. Said that, the error become evident since you are trying to pass a value of type
(Num a, Ord a) => [a]
where a value of type
(a -> b -> c)
is expected.
Rodrigo gave the right answer. I'll just add that it is a misconception to think that some functions need parentheses, while others don't.
This is just like in school math:
3 * (4+5)
It is simply not the case that + expressions need parentheses and * expressions don't need them in general.
In Haskell, you can always get away without parentheses at all. Whenever you need to enclose an expression in parentheses, the alternative is to introduce a local name and bind it to that expression, then use the name instead of the expression.
In your example:
replicate 100 (product (map (*3) (zipWith max [1,2,3,4,5] [4,5,6,7,8])))
let list1 = product list2
list2 = map thrice list3
thrice x = x*3
list3 = zipWith max [1,2,3,4,5] [4,5,6,7,8]
in replicate 100 list1
In fact, I often write functions top down thus:
foo x y z = result
where
result = ...
...
However, as it was said before, expressions that consist of function applications can also often be written without parentheses by making use of (.) and ($) and in such cases, the top down approach from above may be overly verbose and the following would be much clearer (because there is no noise through newly introduced names):
replicate 100
. product
. map (*3)
$ zipWith max [1..5] [4..8]
I want to filter everything that is not divisible by 3 from a list in Haskell, this is technically what I want to do
filter (`mod` 3) [1..100]
The problem is, mod x 3 won't return a boolean value. Is there a way to do this in one line? or am I forced to write another function which returns a boolean value? I've read about curried functions, but I'm not sure if its possible to do this because if I used (==) a b and a is a function, it just wouldn't work out.
That is what function composition is for:
filter ((== 0) . (`mod` 3)) [1..100]
As ever, contemplate the types of the involved functions until everything feels natural.
you can use dot notation
filter ((== 0) . (`mod` 3)) [1..100]
this generates
[3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57,60,63,66,69,72,75,78,81,84,87,90,93,96,99]
The type signature of dot is as follows:
(.) :: (b -> c) -> (a -> b) -> a -> c
If you want to define it in one line and don't want to write another function (which is going to be used in just one place anyway), the easiest way is to define lambda function:
filter (\x -> x `mod` 3 == 0) [1..100]
Point-free style suggested in other answers can sometimes lead to "hard to read" expressions when the auxiliary function is more complex then this. Especially for a beginner.
You can also use a list comprehension:
[x | x <- [1..100], (x `mod` 3) == 0]
An alternative version, using streams:
takeWhile (<=100) $ map (*3) [1..]