I'm trying to get better at playing "type tetris". I have the functions:
(=<<) :: Monad m => (a -> m b) -> m a -> m b zip :: [a] -> [b] -> [(a, b)]
And GHCi tells me:
(zip =<<) :: ([b] -> [a]) -> [b] -> [(a, b)]
I'm having a hard time figuring out how to arrive at that final signature from the first two. My intuition (for lack of a better word) is saying that the first argument of
a -> mb is somehow reconciled against the signature of
zip, and then it should all fall out from that. But I can't understand how to make that leap. Can it be broken down in to a series of easy to follow steps?
It helps to do two things before everything else:
- put explicit parentheses so that
- rename type variables so that there are no clashes
Wit this in mind let's rewrite the types
(=<<) :: Monad m => (a -> m b) -> (m a -> m b) zip :: [x] -> ([y] -> [(x, y)])
Now match the types. The first argument to
(a -> m b) is the same as
[x] -> ([y] -> [(x, y)]).
a -> m b [x] -> ([y] -> [(x, y)])
m b is
([y] -> [(x, y)]). Rewriting
-> in prefix notation, we get
-> [y] [(x, y)], which is the same as
(-> [y]) [(x, y)].
m b (-> [y]) [(x, y)]
(-> [y]) (which is a monad indeed) and
So now we know what is
a, what is
b and what is
m. Let's rewrite
(m a -> m b) in these terms:
(m a) -> (m b) ((-> [y]) [x]) -> ((-> [y]) [(x, y)])
Rewriting in the infix style again, we get
([y] -> [x]) -> ([y] -> [(x, y)])
which is, up to variable names, is the same answer GHC is giving you.