или есть способ объединить эти две функции в одну функцию ... sumOddList
?
Да, есть.
Цепочка функций с помощьюодин вывод как другой работает, особенно при ленивой оценке, но оставляет нас зависимыми от fusion , который должен выполнять компилятор.Что, в конце концов, не гарантируется (и часто не происходит).
Вместо этого то, что вы сказали :
mapping f cons x xs = cons (f x) xs
filtering p cons x xs = if (p x) then (cons x xs) else xs
transduce xf cons z xs = foldr (xf cons) z xs
sumOddList xs = transduce (filtering odd) (+) 0 xs
Таким образом,
> sumOddList [1..10]
25
> sum [1,3..10]
25
> transduce (mapping (+1) . filtering odd) (+) 0 [1..10]
35
> sum . filter odd . map (+1) $ [1..10]
35
> sum . map (+1) . filter odd $ [1..10]
30
> transduce (filtering odd . mapping (+1)) (+) 0 [1..10]
30
Это работает, потому что складывает предохранитель путем составления преобразователей их функций-редукторов (например, mapping
и filtering
выше, которые преобразуют их аргумент редуктора cons
):
foldr (+) 0
. foldr (\x r -> x+1 : r) []
. foldr (\x r -> if odd x then x : r else r) []
$ [1..10]
=
foldr (+) 0
. foldr ((\cons x r -> cons (x+1) r) (:)) []
. foldr ((\cons x r -> if odd x then cons x r else r) (:)) []
$ [1..10]
=
foldr ((\cons x r -> cons (x+1) r) (+)) 0
. foldr ((\cons x r -> if odd x then cons x r else r) (:)) []
$ [1..10]
=
foldr ((\cons x r -> if odd x then cons x r else r)
((\cons x r -> cons (x+1) r) (+))) 0
$ [1..10]
=
foldr ( ( (\cons x r -> if odd x then cons x r else r)
. (\cons x r -> cons (x+1) r) ) (+)) 0
$ [1..10]
=
foldr ( (filtering odd . mapping (+1)) (+)) 0
$ [1..10]
=
foldr ( filtering odd ( mapping (+1) (+))) 0
$ [1..10]
=
30
One foldr
делает работу трех.Fusion явно достигается путем составления функций редуктора после абстрагирования от них операции cons
, каждая такая измененная функция становится преобразователем cons
, таким образом, она может составлять , составленную с другими такими cons
-преобразующими функциями.