1 {-# LANGUAGE ExistentialQuantification #-}
3 -- | Thanks to Gabriel Gonzales and his beautiful folds
6 import Prelude hiding (head, last, all, any, sum, product, length)
8 import qualified Data.Foldable
10 data Fold i o = forall m . Monoid m => Fold (i -> m) (m -> o)
12 fold :: Fold i o -> [i] -> o
13 fold (Fold tally summarize) is = summarize (reduce (map tally is))
15 reduce = Data.Foldable.foldl' (<>) mempty
18 head :: Fold a (Maybe a)
19 head = Fold (First . Just) getFirst
21 last :: Fold a (Maybe a)
22 last = Fold (Last . Just) getLast
24 all :: (a -> Bool) -> Fold a Bool
25 all predicate = Fold (All . predicate) getAll
27 any :: (a -> Bool) -> Fold a Bool
28 any predicate = Fold (Any . predicate) getAny
30 sum :: Num n => Fold n n
33 product :: Num n => Fold n n
34 product = Fold Product getProduct
36 length :: Num n => Fold i n
37 length = Fold (\_ -> Sum 1) getSum
40 {-# LANGUAGE BangPatterns #-}
42 data Average a = Average { numerator :: !a, denominator :: !Int }
44 instance Num a => Monoid (Average a) where
46 mappend (Average xL nL) (Average xR nR) = Average (xL + xR) (nL + nR)
48 average :: Fractional a => Fold a a
49 average = Fold tally summarize
52 summarize (Average numerator denominator) =
53 numerator / fromIntegral denominator