Haskell - foldl和foldr?

时间:2012-11-07 23:34:57

标签: haskell fold

foldlfoldr之间的差异只是循环的方向吗?我认为他们做了什么,而不仅仅是朝这个方向有所不同?

1 个答案:

答案 0 :(得分:101)

如果你的函数不是关联的(即,你将表达式括在哪个方面很重要),那就有区别了,例如,
foldr (-) 0 [1..10] = -5foldl (-) 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的图表(来自wikipedia article);你可以看到f被真正不同的数据对调用:
foldr foldl

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