Pergunta

I'm trying to manually derive the type of ((.) foldr)

(.) ::(b1 -> c1) -> (a1 -> b1) -> a1 -> c1
foldr :: (a2 -> b2 -> b2) -> b2 -> [a2] -> b2

Then:

b1 = a2 -> b2 -> b2
c1 = b2 -> [a2] -> b2

Matching the types I get:

((a2 -> b2 -> b2) -> (b2 -> [a2] -> b2)) -> (a1 -> (a2 -> b2 -> b2)) -> a1 -> (b2 -> [a2] -> b2)

But then I get confused on how to reduce this expresion.

Any help?

Thansks,
Sebastián.

Foi útil?

Solução

Your correctly figured out the type of the (.) in (.) foldr. The (.) is applied to one argument (the foldr) so you can throw away the ((a2 -> b2 -> b2) -> (b2 -> [a2] -> b2)) and what remains is the type of (.) foldr:

(a1 -> a2 -> b2 -> b2) -> a1 -> (b2 -> [a2] -> b2)

Make sure that foldr can have type ((a2 -> b2 -> b2) -> (b2 -> [a2] -> b2)) before you throw it away. If you got the matching right, this check cannot fail, but it is a good sanity check.

Outras dicas

If we have

(.)   :: (b -> c) -> (a -> b) -> (a -> c)
foldr :: (x -> y -> y) -> y -> [x] -> y

Then for (.) foldr, the b -> c has to line up with the type of foldr, so

b             -> c
(x -> y -> y) -> (y -> [x] -> y)

Which implies

b ~ (x -> y -> y)
c ~ (y -> [x] -> y)

So substituting back in:

--                 b                       c
(.) foldr :: (a -> (x -> y -> y)) -> (a -> (y -> [x] -> y))

Since -> is left associative, we can drop the extra parentheses:

(.) foldr :: (a -> x -> y -> y) -> (a -> y -> [x] -> y)

And if you want you can go a step further with

(.) foldr :: (a -> x -> y -> y) -> a -> y -> [x] -> y

So if we ask GHCi what the type is, we get

> :t (.) foldr
(.) foldr :: (a -> a1 -> b -> b) -> a -> b -> [a1] -> b

Where a ~ a, a1 ~ x, and b ~ y, so we've arrived at the correct answer.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top