我正在尝试手动派生((。)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)
但后来我对如何减少这种表达感到困惑。
任何帮助?
Thansks,
安。
答案 0 :(得分:3)
您正确地找出了(.)
中(.) foldr
的类型。 (.)
已应用于一个参数(foldr
),因此您可以丢弃((a2 -> b2 -> b2) -> (b2 -> [a2] -> b2))
,剩下的是(.) foldr
的类型:
(a1 -> a2 -> b2 -> b2) -> a1 -> (b2 -> [a2] -> b2)
确保foldr
在丢弃之前可以使用((a2 -> b2 -> b2) -> (b2 -> [a2] -> b2))
类型。如果你有匹配的权利,这个检查不会失败,但这是一个很好的理智检查。
答案 1 :(得分:1)
如果我们有
(.) :: (b -> c) -> (a -> b) -> (a -> c)
foldr :: (x -> y -> y) -> y -> [x] -> y
然后对于(.) foldr
,b -> 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
,我们已经得到了正确答案。