Using a filtered list in a new function in haskell

后端 未结 3 745
再見小時候
再見小時候 2021-01-19 05:56

So i\'m not too sure how to phrase this properly, but say I wanted to get the sum of all odd numbers in a list, do I have two functions (sumList and getOddNumbers) and combi

3条回答
  •  再見小時候
    2021-01-19 06:35

    or is there a way to put these two together in a single function ... sumOddList?

    Yes there is.

    Chaining functions by using one's output as the other's input works, under lazy evaluation especially, but leaves us reliant on the fusion to be performed by a compiler. Which after all is not guaranteed to happen (and often doesn't).

    Instead, what you said :

    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
    

    Thus,

    > 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
    

    This works because folds fuse by composing their reducer functions' transformers (like the mapping and the filtering above which are transforming their reducer argument 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 doing the work of the three. Fusion explicitly achieved, by composing the reducer functions after the cons operation has been abstracted from them, each such changed function becoming a cons transformer, thus, liable to be composed with other such cons-transforming functions.

提交回复
热议问题