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 ExistentialQuantification #-}
18 {-# LANGUAGE BangPatterns #-}
20 module Gargantext.Core.Utils.Count (head, last, all, any, sum, product, length)
24 import Control.Applicative
25 import qualified Data.Foldable
27 import Control.Lens (Getting, foldMapOf)
29 import Gargantext.Prelude hiding (head, sum, length)
31 data Fold i o = forall m . Monoid m => Fold (i -> m) (m -> o)
33 instance Functor (Fold i) where
34 fmap k (Fold tally summarize) = Fold tally (k . summarize)
36 instance Applicative (Fold i) where
37 pure o = Fold (\_ -> ()) (\_ -> o)
39 Fold tallyF summarizeF <*> Fold tallyX summarizeX = Fold tally summarize
41 tally i = (tallyF i, tallyX i)
42 summarize (nF, nX) = summarizeF nF (summarizeX nX)
44 focus :: (forall m . Monoid m => Getting m b a) -> Fold a o -> Fold b o
45 focus lens (Fold tally summarize) = Fold (foldMapOf lens tally) summarize
48 fold :: Fold i o -> [i] -> o
49 fold (Fold tally summarize) is = summarize (reduce (map tally is))
51 reduce = Data.Foldable.foldl' (<>) mempty
54 head :: Fold a (Maybe a)
55 head = Fold (First . Just) getFirst
57 last :: Fold a (Maybe a)
58 last = Fold (Last . Just) getLast
60 all :: (a -> Bool) -> Fold a Bool
61 all predicate = Fold (All . predicate) getAll
63 any :: (a -> Bool) -> Fold a Bool
64 any predicate = Fold (Any . predicate) getAny
66 sum :: Num n => Fold n n
69 product :: Num n => Fold n n
70 product = Fold Product getProduct
72 length :: Num n => Fold i n
73 length = Fold (\_ -> Sum 1) getSum
76 -- | Average function optimized (/!\ need to test it)
77 data Average a = Average { numerator :: !a, denominator :: !Int }
79 instance Num a => Monoid (Average a) where
81 mappend (Average xL nL) (Average xR nR) = Average (xL + xR) (nL + nR)
83 average :: Fractional a => Fold a a
84 average = Fold tally summarize
87 summarize (Average numerator denominator) =
88 numerator / fromIntegral denominator