Карты и наборы не упорядочены.Стоит ли ожидать различия в производительности между версиями foldl и foldr, определенными для наборов и карт
Если вы ссылаетесь на исходный код Data.Set
или Data.Map
, вы обнаружите, что их элементы организованы в двоичное дерево:
data Map k a = Bin !Size !k a !(Map k a) !(Map k a)
| Tip
data Set a = Bin !Size !a !(Set a) !(Set a)
| Tip
и foldr
из Set:
foldr f z = go z
where
go z' Tip = z'
go z' (Bin _ x l r) = go (f x (go z' r)) l
пересекают деревоиспользуя поиск в глубину с порядком вправо, ток, слева , поэтому, когда foldr (+) 0
применяется к следующему дереву:
1
/ \
4 2
\
3
дает,
4 + (1 + (2 + (3 + 0)))
иfoldl
foldl f z = go z
where
go z' Tip = z'
go z' (Bin _ x l r) = go (f (go z' l) x) r
с заказом влево, ток, вправо при применении foldl (+) 0
к вышеприведенному дереву, дать:
((((0 + 4) + 1) + 2) + 3)
Это показывает, что foldr
и foldl
из набора, эквивалентного указанному, применяются к списку как:
foldr (+) 0 [4, 1, 2, 3] = 4 + (1 + (2 + (3 + 0)))
foldl (+) 0 [4, 1, 2, 3] = ((((0 + 4) + 1) + 2) + 3)
аналогично Data.Map
и не повторяются здесь.
Более того, как мы знали, foldr
может применяться к бесконечному списку (но foldl
не может), например:
take 10 $ foldr ((:) . sum) [] $ chunksOf 3 [1..] = [6,15,24,33,42,51,60,69,78,87]
(здесь chunksOf
группировать список как [[1,2,3], [4,5,6]...]
)
Но как насчеткогда путь к дереву бесконечен, например:
1
/ \
4 2
\
3
\
... <- infinite path
Действует ли foldr
из Set как список, как упомянуто выше?(Я думаю, ответ да, вы можете проверить это сами)
делает ли Foldr f то же самое, что и foldl (флип f)?
Нет , В качестве исходного кода, как показано выше:
foldr = ... go (f x (go z' r)) l
и
foldl (flip f) = ... go (f x (go z' l)) r
Порядок обхода дерева отличается, но общее отношение между foldr
иfoldl
можно найти в этом посте: Определение foldl в терминах foldr