累加器中的累加器

时间:2014-11-22 04:37:56

标签: haskell

在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解释是不正确的,并且只是对称性,在这种情况下它是错误的?

2 个答案:

答案 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)

正如已经指出的那样,{p> 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)