foldl 和 foldr 之间的区别只是循环的方向?我认为他们做了什么,而不仅仅是朝这个方向有所不同?
foldl
foldr
那里有's a difference if your function isn' t关联(即,你将表达式括在哪个方面很重要),例如,foldr (-) 0 [1..10] = -5 但 foldl (-) 0 [1..10] = -55 .在小范围内,这是因为 10-(20-(30)) 与 ((10)-20)-30 不同 .
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 (+) 0 [1..10] = 55
foldl (+) 0 [1..10] = 55
(++)
xs ++ (ys ++ zs)
(xs ++ ys) ++ zs
foldl (++)
有些功能只能以一种方式工作:foldr (:) :: [a] -> [a] -> [a] 但 foldl (:) 是胡说八道 .
foldr (:) :: [a] -> [a] -> [a]
foldl (:)
看看Cale Gibbard的图表(来自wikipedia article);你可以看到 f 被真正不同的数据对调用:
f
另一个区别是因为它匹配列表的结构, foldr 对于延迟评估通常更有效,所以只要 f 在其第二个参数(如 (:) 或 (++) )中是非严格的,就可以与无限列表一起使用 . foldl 很少是更好的选择 . 如果你正在使用 foldl 它通常值得使用 foldl' 因为它是严格的并且阻止你 Build 一长串的中间结果 . (有关this question的答案中有关此主题的更多信息 . )
(:)
foldl'
1 回答
那里有's a difference if your function isn' t关联(即,你将表达式括在哪个方面很重要),例如,
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'
因为它是严格的并且阻止你 Build 一长串的中间结果 . (有关this question的答案中有关此主题的更多信息 . )