我正在学习一些Haskell而我无法理解.我有这个表达式:
flip foldr id
Run Code Online (Sandbox Code Playgroud)
我需要找到它的类型.经过很长一段时间试图解决这个问题,我放弃了并查找了正确的答案,即:
(a -> (a1 -> a1) -> a1 -> a1) -> [a] -> a1 -> a1
Run Code Online (Sandbox Code Playgroud)
但我不明白为什么,我想!我想这[a] -> a1 -> a1
来自foldr
表达,但我不知道如何继续.谢谢你,对不起我的英文!
检查所涉及的各个功能的类型:
? :t id
id :: a -> a
? :t foldr
foldr :: (a -> b -> b) -> b -> [a] -> b
? :t flip
flip :: (a -> b -> c) -> b -> a -> c
Run Code Online (Sandbox Code Playgroud)
然后尝试考虑将这些函数相互应用以查看类型如何匹配.
为了避免在思考时出现名称冲突,我们可以将其flip
类型重写为(a1 -> b1 -> c1) -> b1 -> a1 -> c1
.
这种情况发生的第一件事就是申请flip
到foldr
.纵观类型的flip
和foldr
,我们看到,该类型a1 -> b1 -> c1
中flip
的类型被'匹配了’与类型foldr
.这意味着a1
匹配a -> b -> b
,b1
匹配b
,c1
匹配[a] -> b
.
因此,在这种情况下,flip
's类型变为((a -> b -> b) -> b -> [a] -> b) -> b -> (a -> b -> b) -> [a] -> b
(我只更换每个a1
with a -> b -> c
,each b1
with b
,c1
with each [a] -> b
),并且类型flip foldr
与第一个参数被取消相同:b -> (a -> b -> b) -> [a] -> b
.
到目前为止,我们可以使用ghci查看我们的工作:
? :t flip foldr
flip foldr :: b -> (a -> b -> b) -> [a] -> b
Run Code Online (Sandbox Code Playgroud)
现在我们采用这种类型并将其应用于id
(我们将其编写为a2 -> a2
)的类型.这意味着b
匹配a2 -> a2
,和flip foldr
变成的类型(a2 -> a2) -> (a -> (a2 -> a2) -> (a2 -> a2)) -> [a] -> (a2 -> a2)
,以及flip foldr id
第一个参数带走的类型是相同的:(a -> (a2 -> a2) -> (a2 -> a2)) -> [a] -> a2 -> a2
.这是一样的,你得到了,如果我们只是重写答案a2
为a1
和删除一些括号.