If we start with
(.) :: (b -> c) -> (a -> b) -> (a -> c)
zipWith :: (x -> y -> z) -> [x] -> [y] -> [z]
uncurry :: (u -> v -> w) -> (u, v) -> w
Then we match zipWith
's type with (b -> c)
and uncurry
's type with (a -> b)
:
b -> c
(x -> y -> z) -> ([x] -> [y] -> [z])
And
a -> b
(u -> v -> w) -> ((u, v) -> w)
Then we have to equate the b
terms
b ~ x -> (y -> z)
b ~ (u, v) -> w
So w ~ (y -> z)
and x ~ (u, v)
. A table of what we've determined so far:
a ~ u -> v -> w
b ~ x -> y -> z
c ~ [x] -> [y] -> [z]
x ~ (u, v)
w ~ y -> z
So we can substitute x
and w
in:
a ~ u -> v -> (y -> z)
b ~ (u, v) -> y -> z
c -> [(u, v)] -> [y] -> [z]
And we can now complete the type of zipWith . uncurry
:
(u -> v -> y -> z) -> ([(u, v)] -> [y] -> [z])
Which lines up with GHCi's answer as well.
The trick to these is just to line up the arrows and then just substitute back in until you can't reduce it any more.