3

我正在尝试手动导出 ((.) foldr) 的类型

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

然后:

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

匹配我得到的类型:

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

但是后来我对如何减少这种表达感到困惑。

有什么帮助吗?

谢谢,
塞巴斯蒂安。

4

2 回答 2

3

您正确计算了(.)in的类型(.) foldr。The(.)应用于一个参数 (the foldr),因此您可以丢弃 the ((a2 -> b2 -> b2) -> (b2 -> [a2] -> b2)),剩下的是 的类型(.) foldr

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

在扔掉它之前确保它foldr可以有类型。((a2 -> b2 -> b2) -> (b2 -> [a2] -> b2))如果匹配正确,则此检查不会失败,但它是一个很好的健全性检查。

于 2014-05-01T19:56:50.743 回答
1

如果我们有

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

那么 for (.) foldrb -> c必须与 的类型对齐foldr,所以

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

这意味着

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

所以代入:

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

由于->是左关联的,我们可以去掉额外的括号:

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

如果你愿意,你可以更进一步

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

所以如果我们问 GHCi 是什么类型,我们会得到

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

a ~ a, a1 ~ x, 和, 所以我们b ~ y得到了正确的答案。

于 2014-05-01T20:40:50.220 回答