I'm trying to understand the type of the expression (map . map)
. Since the type of (.)
is (b -> c) -> (a -> b) -> a -> c
I don't understand how this works with the map function, because map takes two arguments which doesn't fit with the functions (b -> c)
and (a -> b)
.
Asked
Active
Viewed 871 times
0

Nicrophorus
- 55
- 4
-
8Mind that `a -> b -> c` is short for `a -> (b -> c)`. In Haskell, all functions only take *one* argument. – Willem Van Onsem Aug 17 '17 at 12:15
-
2I was thinking about that. But I couldn't decide wether it should be split up as `a -> (b -> c)` or `(a -> b) -> c`. But what you say makes sense to me now. Am I correct then if I think about it this way: if we want to consider map as a "one-parameter-function" its type is `(a -> b) -> ([a] -> [b])`, since if we supply it with its first parameter (the `(a -> b)` function) what we get in return is a function of type `([a] -> [b])`. So the types `(a -> b)` and `([a] -> [b])` correspond to the `a` and `b` in `(a -> b)` in the type for `(map . map)`? – Nicrophorus Aug 17 '17 at 13:13
-
3`a -> b -> c` is the same as `a -> (b -> c)` but different that `(a -> b) -> c` – RamiroPastor Aug 17 '17 at 13:20
-
Related question: https://stackoverflow.com/questions/23030638/how-fmap-fmap-typechecks – Sibi Aug 17 '17 at 13:21
2 Answers
5
Quoting GHCI:
Prelude> :t map.map
map.map :: (a -> b) -> [[a]] -> [[b]]
But for map itself, type is
map :: (a -> b) -> [a] -> [b]
which you can see as
map :: (a -> b) -> ([a] -> [b])
So, if we have that
(.) :: (t2 -> t3) -> (t1 -> t2) -> t1 -> t3
Then:
- type
t1
is(a -> b)
- type
t2
is([a] -> [b])
- type
t3
is([[a]] -> [[b]])

RamiroPastor
- 1,085
- 1
- 7
- 18
1
One way I like to think of it is that map
turns an a -> b
into an [a] -> [b]
, so map . map
does it twice. The first map turns your a -> b
into an [a] -> [b]
, and the second map repeats the process, turning it into an [[a]] -> [[b]]
.
"Applying map
to an a -> b
turns it into an [a] -> [b]
", so, it seems pretty pretty logical that applying map
to an [a] -> [b]
would turn it into an [[a]] -> [[b]]
. You're just applying map
to a function twice.
Incidentally:
-- apply map to a function once
map :: (a -> b) -> ( [a] -> [b] )
-- apply map to a function twice
map . map :: (a -> b) -> ( [[a]] -> [[b]] )
-- apply map to a function three times
map . map . map :: (a -> b) -> ([[[a]]] -> [[[b]]])

Justin L.
- 13,510
- 5
- 48
- 83