I tried to find the type of the function
(.) map but somehow find that it is
((a -> d) -> (a -> e)) -> ([d] -> [e]) which according to GHCI is not correct because it should be
(.) map :: (a1 -> a2 -> b) -> a1 -> [a2] -> [b].
What am I doing wrong?
Deriving the type...
We have as ingredients:
(.) :: (b -> c) -> (a -> b) -> a -> c map :: (d -> e) -> [d] -> [e]
(here I used different type identifiers for the two functions to avoid any confusion). A more verbose form (where we make it more explicit that every function takes exactly one parameter) is:
(.) :: (b -> c) -> ((a -> b) -> (a -> c)) map :: (d -> e) -> ([d] -> [e])
map is the first parameter of
(.) that means that its type
(d -> e) -> ([d] -> [e]) should match the input type of the
(.) function (so
b -> c). This thus means:
b -> c ~ (d -> e) -> ([d] -> [e]) ------------------------------ b ~ (d -> e), c ~ ([d] -> [e])
So that means that the result type of
(.) map is:
(a -> b) -> (a -> c)
which is equivalent to:
(a -> (d -> e)) -> (a -> ([d] -> [e]))
or less verbose:
(.) map :: (a -> d -> e) -> a -> [d] -> [e]
... and its implementation
(.) function can be seen as
(.) f g == /x -> f (g x). So that means that our function
h = (.) map
is equivalent to:
h f x = map (f x)
It thus takes as input a function
f and an object
x, and than performs a
f x as function.
Semancially you could say that we make a "map where one has to inject a 'contect'-objecct" of type
a. This context is then taken into account by the processor. This could be useful if we want to apply multiple
maps, each with a small change, and thus first pass a "context-object". This is of course an interpretation of humans. For a compiler, the
x can have any use, interpretation, etc.