I'm new to Haskell and I thought that the functions map map and map.map are the same in Haskell.
My terminal gives me two different types,
(map.map) :: (a -> b) -> [[a]] -> [[b]]
and
(map map) :: [a -> b] -> [[a] -> [b]]
How are those functions different from eachother, in terms of syntax, and what does each one of them mean exactly?
The map map expression will take second map as the parameter of the first one. So that means that if we derive the type, we see:
map :: ( a -> b ) -> ([a] -> [b])
map :: (c -> d) -> ([c] -> [d])
-----------------------------------------------
a ~ (c -> d), b ~ [c] -> [d]
This thus means that a has the same type as c -> d, and b has the same type as [c] -> [d]. It thus means that the type of map map is:
map map :: [a] -> [b]
:: [c -> d] -> [[c] -> [d]]
Here map map thus takes as parameter a list of functions of type c -> d, and it will generate a list of functions that performs a mapping with these functions.
It thus means that if you write:
(map map) [(+1), (*2), (-3)]
you retrieve something like:
[map (+1), map (*2), map (-3)]
That is not the case for map . map. This expression is equivalent to (.) map map. The (.) :: (b -> c) -> (a -> b) -> a -> c function takes two functions f and g, and combines these as \x -> f (g x). The type thus means:
(.) :: ( b -> c ) -> (( a -> b ) -> (a -> c))
map :: (d -> e) -> ([d] -> [e])
map :: (f -> g) -> ([f] -> [g])
-------------------------------------------------------------------------
b ~ d -> e ~ [f] -> [g], c ~ [d] -> [e], a ~ f -> g, d ~ f, e ~ g
The type of (.) map map is thus:
(.) map map :: a -> c
:: (f -> g) -> ([d] -> [e])
:: (f -> g) -> ([[f]] -> [[g]])
This function takes a single function of type f -> g, and will generate a function that takes a list of list of fs and it can map these to gs.
So (map . map) (+1) will generate a function such that for:
(map . map) (+1) [[1,4,2,5],[1,3,0,2]]
it will generate:
[[2,5,3,6], [2,4,1,3]]
map . map ≡ (\x -> map (map x))
≡ (\x y -> map (map x) y)
map map ≡ map (map)
≡ (\x -> map map x)
So, basically the . smuggles an extra variable into the “function bracket” of the outer map.
It turns map (map) x into map (map x). Both mean something quite different, as the types demonstrate.
In map (map x) y, the x is a function that'll be applied to the inner elements of the nested list y, because map x (partial application) is a list-mapping function. Whereas in map map x, the higher-order function map itself is mapped over the list. That sounds strange but it is possible, it just requires a list of functions (which will be the functions that the inner map maps) and spits out another list of functions (each of which does the mapping over one particular inner list).
Related
f = filter . flip notElem
I am wondering how this line works, this is a function that should take two strings and return a string.
flip :: (b -> a -> c) -> a -> b -> c flips the first two parameters of a function. So since notElem :: Eq a => a -> [a] -> Bool takes a value and a list to check if the value is not in the list, flip notElem :: Eq a => [a] -> a -> Bool takes a list and a value to check if it is not in the list.
We thus will first partially apply the first parameter in f to flip notElem, and then filter a list. Your expression is thus a short form of:
f :: Eq a => [a] -> [a] -> [a]
f xs ys = filter (\y -> notElem y xs) ys
It will thus return all elements in ys (the second parameter) that are not in xs (the first parameter). For example:
Prelude> f [1,3,0,2] [1,4,2,5]
[4,5]
Both 4 and 5 are elements of the second list, but not of the first one.
I have an intricate Haskell function:
j :: [Int]
j = ((\f x -> map x) (\y -> 3 + y) (\z -> 2*z)) [1,2,3]
My guess was that (\y -> 3 + y) (\z -> 2*z) will change to (\w -> 3 + 2*w) and together with f there should be print out the list [5,7,9].
When I checked with ghci I got [2,4,6] as a result.
Question: So is (\y -> 3 + y) a redundant expression here? If so, why?
I think you've gone wrong somewhere in the design of your function, but I'll give you an explanation of the mechanics going on here. Stick around for the detailed explanation if you still get stuck understanding.
Quick answer: Evaluating the expression
j = ((\f x -> map x) (\y -> 3 + y) (\z -> 2*z)) [1,2,3]
= ((\x -> map x) (\z -> 2*z)) [1,2,3]
= (map (\z -> 2*z)) [1,2,3] -- f := (\y -> 3 + y), x := (\z -> 2*z)
= [2,4,6]
You may see that when Haskell evaluates (\f x -> map x) (\y -> 3 + y), which it will because function applications are evaluated left-to-right, the substitution f := (\y -> 3 + y) is made, but f doesn't appear anywhere in the function, so it just becomes (\x -> map x).
Detailed answer: Left (and Right) associative operators
In Haskell we say that function application is left associative. This is to say, when we write a function application, it is evaluated like so:
function arg1 arg2 arg3 = ((function arg1) arg2) arg3
No matter what the types of the arguments are. This is called left associative because the brackets are always on the left.
You seem to expect your expression to behave like this:
(\f x -> map x) (\y -> 3 + y) (\z -> 2*z)
= (\f x -> map x) ((\y -> 3 + y) (\z -> 2*z)) -- Incorrect
However, as we've seen, functions associate left, not right as you assumed, and so your expression looks to Haskell like this:
(\f x -> map x) (\y -> 3 + y) (\z -> 2*z)
= ((\f x -> map x) (\y -> 3 + y)) (\z -> 2*z)
= (\x -> map x) (\z -> 2*z) -- Correct!
Notice that the brackets I put in to order the evaluation are on the left, not the right.
However, Haskell has defined a very useful right-associative function application operator, namely ($) :: (a -> b) -> a -> b. You could re-write your expression like so to obtain the result you seemed to expect.
(\f x -> map x) $ (\y -> 3 + y) (\z -> 2*z)
= (\f x -> map x) $ ((\y -> 3 + y) (\z -> 2*z)) -- Correct, though nonsensical.
However, as you'll notice, f still isn't referred to in (\f x -> map x) and so is ignored entirely. I'm not sure exactly what your goal was in making this function
Further issue: Lambda expressions & composition
I realise that another issue may be your understanding of lambda expressions. Consider this function:
f x = x + 2
We could re-write this as a lambda expression, like so:
f = \x -> x+2
However, what if we have two arguments? This is what we do:
g x y = x + y
g = \x -> (\y -> x+y)
The way Haskell models multiple arguments is called currying. You can see that the function actually returns another function, which then returns a function that finally returns what it should have. However, this notation is long and cumbersome, so Haskell provides an alternative:
g = \x y -> x + y
This may seem to be different, but in fact it is syntactic sugar for exactly the same expression as before. Now, looking at your first lambda expression:
\f x -> map x = \f -> (\x -> map x)
You can see that the argument f isn't actually referred to at all in the function, so if I apply something to it:
(\f x -> map x) foo
= (\f -> (\x -> map x)) foo
= \x -> map x
That's why your (\y -> 3 + y) is ignored; you haven't actually used it in your functions.
Furthermore, you expect the expression (\y -> 3 + y) (\z -> 2*z) to evaluate to \w -> 3 + 2*w. This is not true. The lambda on the left replaces each occurrence of y with (\z -> 2*z), so the result is the completely nonsensical 3 + (\z -> 2*z). How do you add a function to a number?!
What you're looking for is called composition. We have an operator in Haskell, namely (.) :: (b -> c) -> (a -> b) -> (a -> c) which can help you with this. It takes a function on the left and the right and creates a new function that 'pipes' the functions into each other. That is to say:
(\y -> 3 + y) . (\z -> 2*z) = \w -> 3 + 2*w
Which is what you're looking for.
Conclusion: Corrected expression
I think the expression you're looking for is:
j = ( (\x -> map x) $ (\y -> 3 + y) . (\z -> 2*z) ) [1,2,3]
Which is equivalent to saying:
j = map (\w -> 3 + 2*w) [1,2,3]
Since you seem to be having a lot of trouble with the more basic parts of Haskell, I'd recommend the quintessential beginner's book, Learn You a Haskell for Great Good.
It is because it goes the other way round, that is you apply (\f x -> map x) to (\y -> 3 + y) first. But
(\f x -> map x) something g
becomes
let f = something; x = g in map x
And this finally is
map g
So something doesn't appear in the resulting expression, since f is not mentioned anywhere right from the arrow.
If I understand you correctly, you want
(\f x -> map (f . x))
Additional note: From your argumentation, it looks like you have not grasped yet how beta reduction works.
For example, even if the expressions would be applied like you think:
(\y -> 3 + y) (\z -> 2*z)
the result would be
3 + (\z -> 2*z)
No, it is doubtful that this makes any sense, however, it's the way beta reduction works: It gives the part right from the arrow where every occurrence of a parameter is replaced by the actual argument.
I'm learning Haskell. I defined the following function (I know I don't need addToList and I can also do Point-free notation I'm just in the process of playing with language concepts):
map :: (a -> b) -> [a] -> [b]
map f [] = []
map f (x:xs) = addToList (f x) map f xs
where
addToList :: a -> [a] -> [a]
addToList x [] = [x]
addToList x xs = x:xs
This produces a compile error:
with actual type `(a0 -> b0) -> [a0] -> [b0]'
Relevant bindings include
f :: a -> b (bound at PlayGround.hs:12:5)
map :: (a -> b) -> [a] -> [b] (bound at PlayGround.hs:11:1)
Probable cause: `map' is applied to too few arguments
In the second argument of `addToList', namely `map'
In the expression: addToList (f x) map f xs
If I put parantheses around map it works:
map :: (a -> b) -> [a] -> [b]
map f [] = []
map f (x:xs) = addToList (f x) (map f xs)
where
addToList :: a -> [a] -> [a]
addToList x [] = [x]
addToList x xs = x:xs
I understand that function application binds more tightly than operators (as discussed in Haskell - too few arguments), however, I don't understand how the compiler would parse the above differently without the parantheses.
The simple way to see that something is wrong is to note that the expression:
addToList (f x) map f xs
is applying 4 arguments to addToList whereas:
addToList (f x) (map f xs)
is applying two arguments to addToList (which is what addToList "expects").
Update
Note that even though map takes two arguments, this expression:
addToList a map c d
is parsed as:
(((addToList a) map) c) d
So here's a possible explanation of what GHC is thinking...
addToList (f x) has type [a] -> [a] - i.e. it is a function which takes a list.
map has type (c -> d) -> [c] -> [d]. It is not a list, but with additional arguments it could produce a list.
So when GHC sees addTolist (f x) map and can't type check it, it sees that if map only had a few more arguments, like this:
addToList (f x) (map ...)
at least the second argument to addToList would be a list - so perhaps that's the problem.
Parsing is a distinct step that is completed before type checking occurs. The expression
addToList (f x) map f xs
has as much meaning to the parser as s1 (s2 s3) s4 s2 s5 has to you. It doesn't know anything about what the names mean. It takes the lexical structure of the string and turns it into a parse tree like
*5
/ \
/ xs
*4
/ \
/ f
*3
/ \
/ map
*2
/ \
addToList *1
/ \
f x
Once the parse tree is complete, then each node is tagged with its type, and type checking can occur. Since function application is denoted simply by juxtaposition, the type checker knows that the left child of a node is a function, the right child is the argument, and the root is the result.
The type checker can proceed roughly as follows, doing an pre-order traversal of the tree. (I'll alter the type signatures slightly to distinguish unrelated type variables until they are unified.)
addToList :: a -> [a] -> [a], so it takes an argument of type a and returns a function of type [a] -> [a]. The value of a is not yet known.
f :: b -> c, so it takes an argument of type b and returns a value of type c. The values of b and c are not yet known.
x has type d. The value of d is not yet known.
Letting b ~ d, f can be applied to x, so *1 :: c
Letting a ~ c, addToList is applied to *1, so *2 :: [a] -> [a]
Uh oh. *2 expects an argument of type [a], but it is being applied to map :: (e -> f) -> [e] -> [f]. The type checker does not know how to unify a list type and a function type, which produces the error you see.
So I was taking a test about Haskell and one question said:
let the function be
lolo g x = ys
where ys = [x] ++ filter (curry g x) ys
then determine the type of the function called lolo. The options are:
a) (a,b) -> Bool -> b -> [(a,b)]
b) (b -> b -> b) -> Bool -> [b]
c) ((b,b) -> Bool) -> b -> [b]
d) (a -> b -> Bool) -> b -> [c]
Can somebody please explain which one it is and why? I'm really confused about this one... things I do not understand are:
1) the curry function can only be applied to functions right? not datatypes that may be tuples? then you can infer that g is a function in this context? what if g and x are both functions? is it possible to use curry with nth arguments? I've only seen curry used with 1 argument.
2) the other thing I don't understand very much is the recursion in the definition of ys. so ys is defined by ys, but I don't see the base case in this scenario. Will it ever end? maybe it's the filter function that makes the recursion end.
3) also in curry g x = curry (g x) right? (this is a question about precedence in application of functions)
Thanks a lot
1) The first argument to curry has to be a function, it is what is known as a higher order function, it takes a function and returns a new one. While its type is printed out in GHCi as
curry :: ((a, b) -> c) -> a -> b -> c
It is more clearly represented (IMO) as
curry :: ((a, b) -> c) -> (a -> b -> c)
Which makes it more obvious that it takes a function and returns a new function. Technically, you could say that curry takes 3 arguments, one of type (a, b) -> c, one of type a, and one of type b. It just takes a function that normally accepts a tuple of arguments and converts it into a function that takes 2 arguments.
2) The computation for ys will never end, don't bother trying to call length on it, you'll just run the computation forever. This isn't a problem, though, you can work with infinite lists and non-terminating lists just fine (non-terminating being a list where it takes forever to compute the next element, not just one that has infinite elements). You can still use functions like take and drop on it, though.
3) Does curry g x == curry (g x)? No! When you see an expression like a b c d e, all of b, c, d, and e are arguments to a. If you instead saw a b c (d e), then e is applied to d, and that result is applied to a b c. Consider filter even [1..10], this is certainly not the same as filter (even [1..10]), since it wouldn't even compile! (even :: Integral a => a -> Bool).
When solving this sort of problem, first look at what functions are used in the expression that you already know the types of:
(++) :: [a] -> [a] -> [a]
filter :: (b -> Bool) -> [b] -> [b]
curry :: ((c, d) -> e) -> c -> d -> e
I've used different type variables in each so that there will be less confusion when trying to line up the types. You can get these types by loading up GHCi, then typing
> :type (++)
(++) :: [a] -> [a] -> [a]
> -- Or just use :t
> :t filter
filter :: (a -> Bool) -> [a] -> [a]
> :t curry
curry :: ((a, b) -> c) -> a -> b -> c
As you can see, I've changed filter to use b instead of a, and curry to use c, d, and e. This doesn't change the meaning any more than f x = x + 1 versus f y = y + 1, it'll just make it easier to talk about.
Now that we've broken down our function into its subcomponents, we can work from the "top" down. By top, I mean the last function that gets called, namely (++). You can picture this function by a tree like
(++)
/ \
[x] filter
/ \
curry ys
/ \
g x
So we can clearly see that (++) is at the top. Using that, we can infer that [x] has the type [a], which means that x ~ a (the tilde is the type equality symbol) and consequently ys ~ [a], since ys = [x] ++ something. Now that we know the type of x, we can start filling out the rest of the expression. Next, we work down to filter (curry g x) ys. Since it is the second argument to (++), we can infer that this subexpression also has the type [a]. If we look at the type of filter:
filter :: (b -> Bool) -> [b] -> [b]
The final result is a list of type [b]. Since it's being applied to [x] ++, we can infer that filter (curry g x) ys :: [a]. This means that [b] ~ [a] => b ~ a. For reference, this makes filter's type
filter :: (a -> Bool) -> [a] -> [a]
This now places a constraint on curry g x, it must fit into filter's first argument which has the type a -> Bool. Looking at curry's type again:
curry :: ((c, d) -> e) -> c -> d -> e
This means that e ~ Bool, and d ~ a. If we plug those back in
curry :: ((c, a) -> Bool) -> c -> a -> Bool
Ignoring g for now, we look at the type of x, which we figured out is a. Since x is the second argument to curry, that means that x matches with the argument of type c, implying that c ~ a. Substituting this into what we just computed we get
curry :: ((a, a) -> Bool) -> a -> a -> Bool
With
curry g x :: a -> Bool
filter (curry g x) :: [a] -> [a]
filter (curry g x) ys :: [a]
[x] ++ filter (curry g x) ys :: [a]
From this we can directly infer that lolo's type signature ends with [a], so
lolo :: ??? -> [a]
I'll leave you to do the remaining few steps to figure out what ??? is.
How can be iterate function modified that the result will be
f x, (f^2)x, (f^4)x, (f^8)x, ...
I'd be very happy if anybody could provide me with any suggestion.
Given, that f^x means f x-times applied to x I would say
iterate :: (a -> a) -> a -> [a]
iterate f x = f x : iterate (f . f) x
would suffice.
Alternative:
Prelude> map snd $ iterate (\(f,x) -> (f.f, f x)) ((+1),1)
[1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,...