2 Module : Gargantext.Core.Utils.Count
4 Copyright : (c) CNRS, 2017-Present
5 License : AGPL + CECILL v3
6 Maintainer : team@gargantext.org
7 Stability : experimental
10 Here is a longer description of this module, containing some
11 commentary with @some markup@.
13 Inspired from Gabriel Gonzales, "beautiful folds" talk.
17 {-# LANGUAGE NoImplicitPrelude #-}
18 {-# LANGUAGE ExistentialQuantification #-}
19 {-# LANGUAGE BangPatterns #-}
20 {-# LANGUAGE RankNTypes #-}
22 module Gargantext.Core.Utils.Count (head, last, all, any, sum, product, length)
26 import Control.Applicative
27 import qualified Data.Foldable
29 import Control.Lens (Getting, foldMapOf)
31 import Gargantext.Prelude hiding (head, sum, length)
33 data Fold i o = forall m . Monoid m => Fold (i -> m) (m -> o)
35 instance Functor (Fold i) where
36 fmap k (Fold tally summarize) = Fold tally (k . summarize)
38 instance Applicative (Fold i) where
39 pure o = Fold (\_ -> ()) (\_ -> o)
41 Fold tallyF summarizeF <*> Fold tallyX summarizeX = Fold tally summarize
43 tally i = (tallyF i, tallyX i)
44 summarize (nF, nX) = summarizeF nF (summarizeX nX)
46 focus :: (forall m . Monoid m => Getting m b a) -> Fold a o -> Fold b o
47 focus lens (Fold tally summarize) = Fold (foldMapOf lens tally) summarize
50 fold :: Fold i o -> [i] -> o
51 fold (Fold tally summarize) is = summarize (reduce (map tally is))
53 reduce = Data.Foldable.foldl' (<>) mempty
56 head :: Fold a (Maybe a)
57 head = Fold (First . Just) getFirst
59 last :: Fold a (Maybe a)
60 last = Fold (Last . Just) getLast
62 all :: (a -> Bool) -> Fold a Bool
63 all predicate = Fold (All . predicate) getAll
65 any :: (a -> Bool) -> Fold a Bool
66 any predicate = Fold (Any . predicate) getAny
68 sum :: Num n => Fold n n
71 product :: Num n => Fold n n
72 product = Fold Product getProduct
74 length :: Num n => Fold i n
75 length = Fold (\_ -> Sum 1) getSum
78 -- | Average function optimized (/!\ need to test it)
79 data Average a = Average { numerator :: !a, denominator :: !Int }
81 instance Num a => Monoid (Average a) where
83 mappend (Average xL nL) (Average xR nR) = Average (xL + xR) (nL + nR)
85 average :: Fractional a => Fold a a
86 average = Fold tally summarize
89 summarize (Average numerator denominator) =
90 numerator / fromIntegral denominator