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?
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])
Since 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]
The (.) 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 map with 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With