【问题标题】:Accumulator in foldrfoldr 中的累加器
【发布时间】:2014-11-22 04:37:55
【问题描述】:

在 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 是操作的标识值(例如 sum 为 0 或 product 为 1),其值在函数执行期间不会改变。那么为什么在这里和其他文本中都将它称为累加器,暗示它逐步改变或累积一个值?

我可以看到累加器与左折叠相关,例如 foldl,但 wikibook 的解释是否不正确,仅出于对称性,在这种情况下是错误的?

【问题讨论】:

  • foldl 中的累积从左侧发生,foldr 中的累积从右侧发生。
  • 是的,这很有趣。将f 的第二个参数称为累加器可能更合适。我通常用z(表示零)或nil(表示它对应的构造函数大小写)来编写foldr-esque模式。

标签: haskell


【解决方案1】:

考虑基于您提供的(正确)定义对简单的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

【讨论】:

  • 嗯,它是一个不会改变的累加器:P
【解决方案2】:

正如已经指出的那样,accfoldr 的情况下并没有真正积累任何东西。

如果没有它,我会补充一点,当输入为空列表时,不清楚会发生什么。

它还改变了f的类型签名,限制了可以使用的功能。

例如:

foldr' :: (a -> a -> a) -> [a] -> a
foldr' f [] = error "empty list???"
foldr' f (x:[]) = x
foldr' f (x:xs) = f x (foldr' f xs)

【讨论】:

  • 你描述的是foldr1,它确实在空列表上出错。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-12
相关资源
最近更新 更多