На самом деле, (foldl.foldr) f z xs === foldr f z (concat $ reverse xs)
.
Даже если f
является ассоциативной операцией, имеет значение правильная последовательность приложений, так как это может повлиять на производительность.
Мы начинаем с
(foldl.foldr) f z xs
foldl (foldr f) z xs
письменной форме с g = foldr f
и [x1,x2,...,xn_1,xn] = xs
на мгновение, это
(...((z `g` x1) `g` x2) ... `g` xn)
(`g` xn) ((`g` xn_1) ... ((`g` x1) z) ...)
foldr f z $ concat [xn,xn_1, ..., x1]
foldr f z $ concat $ reverse xs
Так что в вашем случае правильная последовательность редукция
(foldl.foldr) 1 [[1,2,3],[4,5,6]]
4+(5+(6+( 1+(2+(3+ 1)))))
22
К остроумию ,
Prelude> (foldl.foldr) (:) [] [[1..3],[4..6],[7..8]]
[7,8,4,5,6,1,2,3]
Аналогично, (foldl.foldl) f z xs == foldl f z $ concat xs
. С snoc a b = a++[b]
,
Prelude> (foldl.foldl) snoc [] [[1..3],[4..6],[7..8]]
[1,2,3,4,5,6,7,8]
Кроме того, (foldl.foldl.foldl) f z xs == (foldl.foldl) (foldl f) z xs == foldl (foldl f) z $ concat xs == (foldl.foldl) f z $ concat xs == foldl f z $ concat (concat xs)
и т.д .:
Prelude> (foldl.foldl.foldl) snoc [] [[[1..3],[4..6]],[[7..8]]]
[1,2,3,4,5,6,7,8]
Prelude> (foldl.foldr.foldl) snoc [] [[[1..3],[4..6]],[[7..8]]]
[7,8,1,2,3,4,5,6]
Prelude> (foldl.foldl.foldr) (:) [] [[[1..3],[4..6]],[[7..8]]]
[7,8,4,5,6,1,2,3]
Я не думаю, что это правильная последовательность приложений, Daniel. '7' не будет принудительным, как вы покажете, ИМО. –
Да, это будет - запрет на оптимизацию - останется до тех пор, пока не будет оценен окончательный результат, полученный от 'foldl'. Но преждевременно оценить его было меньше, и он стал более читаемым. –