在Haskell Wikibook中,foldr实现如下:
foldr :: (a -> b -> b) -> b -> [a] -> b
foldr f acc [] = acc
foldr f acc (x:xs) = f x (foldr f acc xs)
声明累加器的初始值被设置为参数。但据我了解,acc是操作的标识值(例如0表示sum或1表示产品),其值在执行函数期间不会改变。那么为什么它在这里和其他文本中被称为累加器,暗示它逐步改变或积累一个值?
我可以看到累加器在左侧折叠中是相关的,例如foldl,但是wikibook解释是不正确的,并且只是对称性,在这种情况下它是错误的?
答案 0 :(得分:10)
根据您提供的(正确)定义,考虑对简单foldr
表达式的评估:
foldr (+) 0 [1,2,3,4]
= 1 + foldr (+) 0 [2,3,4]
= 1 + 2 + foldr (+) 0 [3,4]
= 1 + 2 + 3 + foldr (+) 0 [4]
= 1 + 2 + 3 + 4 + foldr (+) 0 []
= 1 + 2 + 3 + 4 + 0
= 10
所以你是对的:acc
并没有真正地积累"任何东西。它永远不会使用0
以外的值。
为什么叫它" acc"如果它不是累加器?与foldl
相似? Hysterical raisins?一个lie to children?我不确定。
编辑:我还要指出foldr
的GHC实施使用z
(大概为零)而不是acc
。
答案 1 :(得分:1)
acc
并没有在foldr
的情况下积累任何东西。
如果没有它,我会补充一点,当输入为空列表时,不清楚会发生什么。
它还会更改f
的类型签名,限制可以使用的功能。
E.g:
foldr' :: (a -> a -> a) -> [a] -> a
foldr' f [] = error "empty list???"
foldr' f (x:[]) = x
foldr' f (x:xs) = f x (foldr' f xs)