문제

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.

도움이 되었습니까?

해결책

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.

다른 팁

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.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top