foldl
和foldr
之间的差异只是循环的方向吗?我认为他们做了什么,而不仅仅是朝这个方向有所不同?
答案 0 :(得分:101)
如果你的函数不是关联的(即,你将表达式括在哪个方面很重要),那就有区别了,例如,
foldr (-) 0 [1..10] = -5
但foldl (-) 0 [1..10] = -55
在小范围内,这是因为10-(20-(30))
与((10)-20)-30
不同。
因为(+)
是关联的(无论你添加子表达式的顺序如何),
foldr (+) 0 [1..10] = 55
和foldl (+) 0 [1..10] = 55
。 (++)
是另一个关联操作,因为xs ++ (ys ++ zs)
给出的答案与(xs ++ ys) ++ zs
相同(尽管第一个答案更快 - 请勿使用foldl (++)
。
有些功能只能单向工作:
foldr (:) :: [a] -> [a] -> [a]
但foldl (:)
是无稽之谈。
看看Cale Gibbard的图表(来自wikipedia article);你可以看到f
被真正不同的数据对调用:
另一个区别是因为它匹配列表的结构,foldr
通常对于延迟评估更有效,所以只要f
非严格,就可以使用无限列表它的第二个参数(如(:)
或(++)
)。 foldl
很少是更好的选择。如果你正在使用foldl
,那么通常值得使用foldl'
因为它是严格的并且阻止你建立一长串的中间结果。 (有关this question的答案中有关此主题的更多信息。)