Haskell - foldl和foldr?

Let*_*thi 50 haskell fold

循环的方向foldlfoldr方向之间的区别是什么?我认为他们所做的不同,而不只是方向?

And*_*ewC 104

如果你的函数不是关联的(例如,你将表达式括在哪个方面),那就有区别了,例如,
foldr (-) 0 [1..10] = -5但是foldl (-) 0 [1..10] = -55.
在小范围内,这是因为10-(20-(30))不一样((10)-20)-30.

而因为因为(+)是关联的(无论你添加子表达式的顺序是什么),
foldr (+) 0 [1..10] = 55foldl (+) 0 [1..10] = 55.(++)是另一个关联操作,因为xs ++ (ys ++ zs)给出相同的答案(xs ++ ys) ++ zs(虽然第一个更快 - 不要使用foldl (++).

有些功能只能以一种方式工作:
foldr (:) :: [a] -> [a] -> [a]但这foldl (:)是无稽之谈.

看看Cale Gibbard的图表(来自维基百科文章); 您可以看到f使用真正不同的数据对调用:
foldr相似与foldl

另一个区别是因为它匹配列表的结构,foldr对于延迟评估通常更有效,因此只要f在第二个参数(如(:)(++))中是非严格的,就可以使用无限列表.foldl很少是更好的选择.如果你正在使用foldl它通常值得使用,foldl'因为它是严格的,并阻止你建立一长串的中间结果.(更多关于这个话题的回答这个问题.)

  • 与最后一点相关的另一个区别是,如果给出一个无限列表,`foldl`永远不会返回,而如果在第二个参数中给出一个非严格的函数,则`foldr`将会返回(例如`(:)`或者`const`,...) (9认同)
  • 它的关联性很重要,而不是交换性.我可以用foldr和foldl乘以矩阵,这样可以得到相同的结果. (3认同)
  • 但是,语义上的差异不仅仅是句法上的差异:`foldr (:) "!" "Hello"` 是 `"Hello!"` 而 `foldl (flip (:)) "!" “你好”`是`“olleH!”` (3认同)