【发布时间】:2020-12-16 09:23:00
【问题描述】:
在标题为“Haskell 编程”的书中,第 77 页,有一个 foldr 的实现,以解释该功能。它看起来像这样:
foldr :: (a -> b -> b) -> b -> [a] -> b
foldr f v [] = v
foldr f v (x:xs) = f x (foldr f v xs)
为什么不是这样的类型:
foldr :: (a -> a -> b) -> a -> [a] -> b
第一个参数,它是一个函数(a -> b -> b),将始终应用于列表的头部,以及递归处理的尾部。
但是有什么例子,头部和递归处理的尾部最终具有不同的类型?
我肯定不明白这里的一些东西。你能分解一下为这个 foldr 实现编写类型的过程吗?
【问题讨论】:
-
foldr (:) []是一个简单的例子。这里你构造一个列表,所以这里是b ~ [a]。 -
请注意,第二个参数是在列表尾部递归的结果,因此它也是
b。 -
"但是有什么例子,头部和递归处理的尾部最终具有不同的类型?"。如果头部和递归处理的尾部总是具有相同的类型,则签名将归结为
foldr :: (a -> a -> a) -> a -> [a] -> a,因为在这种情况下,“折叠函数”不能返回与a不同的东西,因此 foldr 的输出类型也应该是a。 -
this question 上的现有答案也可能会有所帮助。
标签: haskell