1module Data.Foldable.Extra
2    ( module Data.Foldable
3    , sum'
4    , product'
5    , sumOn'
6    , productOn'
7    , anyM
8    , allM
9    , orM
10    , andM
11    , findM
12    , firstJustM
13    ) where
14
15import Data.Foldable
16import qualified Control.Monad.Extra as MX
17
18-- | A generalization of 'Data.List.Extra.sum'' to 'Foldable' instances.
19sum' :: (Foldable f, Num a) => f a -> a
20sum' = foldl' (+) 0
21
22-- | A generalization of 'Data.List.Extra.product'' to 'Foldable' instances.
23product' :: (Foldable f, Num a) => f a -> a
24product' = foldl' (*) 1
25
26-- | A generalization of 'Data.List.Extra.sumOn'' to 'Foldable' instances.
27sumOn' :: (Foldable f, Num b) => (a -> b) -> f a -> b
28sumOn' f = foldl' (\acc x -> acc + f x) 0
29
30-- | A generalization of 'Data.List.Extra.productOn'' to 'Foldable' instances.
31productOn' :: (Foldable f, Num b) => (a -> b) -> f a -> b
32productOn' f = foldl' (\acc x -> acc * f x) 1
33
34-- | A generalization of 'Control.Monad.Extra.anyM' to 'Foldable' instances. Retains the short-circuiting behaviour.
35anyM :: (Foldable f, Monad m) => (a -> m Bool) -> f a -> m Bool
36anyM p = foldr ((MX.||^) . p) (pure False)
37
38-- | A generalization of 'Control.Monad.Extra.allM' to 'Foldable' instances. Retains the short-circuiting behaviour.
39allM :: (Foldable f, Monad m) => (a -> m Bool) -> f a -> m Bool
40allM p = foldr ((MX.&&^) . p) (pure True)
41
42-- | A generalization of 'Control.Monad.Extra.orM' to 'Foldable' instances. Retains the short-circuiting behaviour.
43orM :: (Foldable f, Monad m) => f (m Bool) -> m Bool
44orM = anyM id
45
46-- | A generalization of 'Control.Monad.Extra.andM' to 'Foldable' instances. Retains the short-circuiting behaviour.
47andM :: (Foldable f, Monad m) => f (m Bool) -> m Bool
48andM = allM id
49
50-- | A generalization of 'Control.Monad.Extra.findM' to 'Foldable' instances.
51findM :: (Foldable f, Monad m) => (a -> m Bool) -> f a -> m (Maybe a)
52findM p = foldr (\x -> MX.ifM (p x) (pure $ Just x)) (pure Nothing)
53
54-- | A generalization of 'Control.Monad.Extra.firstJustM' to 'Foldable' instances.
55firstJustM :: (Foldable f, Monad m) => (a -> m (Maybe b)) -> f a -> m (Maybe b)
56firstJustM p = MX.firstJustM p . toList
57