Reputation: 349
I was going over a self-graded quizes for Haskell MOOC and could not figure out the following question:
If f :: a -> b, then what is the type of map (.f)?
where the answer is the following:
[b -> c] -> [a -> c] -- correct answer
-- below are wrong answers
[c -> a] -> [c -> b]
(b -> c) -> [a -> c]
[a] -> [b]
I understand that map
's type is (a -> b) -> [a] -> [b]
according to the map
's documentation so I can sort of see why you would get a list ([a -> c]
) for the output.
However, I don't understand why the input for this becomes a list ([b -> c]
) given that the function f
is a -> b
. Since the input is a function, why wasn't the input type (b -> c)
? (also, why is it using b -> c
instead of a -> b
?)
Furthermore, I was wondering why it's .f
rather than f
; I thought that the function composition (.
) needed to be in the following format: map . f
, but does .f
mean something else in this case?
Thank you in advance for your assistance.
Upvotes: 0
Views: 63
Reputation: 5063
Deducing the type of some expression is a mechanical work, and kind of fun!
-- You can use :t exp in ghci to cheat, but is worth doing it by hand a few times
-- suggestion: For each expression use different set of variables
-- 1) write every part and its type
(.) :: (b -> c) -> (a -> b) -> a -> c
f :: x -> z
map :: (m -> n) -> [m] -> [n]
-- 2) build small steps.
-- In ( . f) you are applying f as the second argument of .
-- you only need to be carefull with variable names.
-- Align arguments as they are applied
(.) :: (b -> c) -> (a -> b) -> a -> c
f :: x -> z
-- Hence (symbol a ~ b means a is the same type as b)
a ~ x
b ~ z
-- Consuming the second output and use the names of f to make it clearer
(.) :: (b -> c) -> (a -> b) -> a -> c
f :: x -> z
( . f) :: (z -> c) -> x -> c
-- 3) do the same with the whole expresion
-- map ( . f) uses (. f) as its first argument
-- Tricky. Notice that the WHOLE expression (. f) is just the first argument of map
map :: ( m -> n ) -> [m] -> [n]
( . f) :: ( (z -> c) -> x -> c )
-- Hence. Notice that m and n are
m ~ z -> c
n ~ x -> c
-- Hence, comsume the first parameter and substite variable names
map :: ( m -> n ) -> [m] -> [n]
( . f) :: ( (z -> c) -> x -> c )
map ( . f) :: [z -> c] -> [x -> c]
-- 4) make var names more digestive. Keep in mind that in step 2) x ~ a and b ~ z
map ( . f) :: [b -> c] -> [a -> c]
Upvotes: 2