{-# OPTIONS_GHC -Wno-redundant-constraints #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE Safe #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
module Relude.Foldable.Fold
( flipfoldl'
, asumMap
, foldMapA
, foldMapM
, sum
, product
, elem
, notElem
, allM
, anyM
, andM
, orM
) where
import GHC.TypeLits (ErrorMessage (..), Symbol, TypeError)
import Relude.Applicative (Alternative, Applicative (..), pure)
import Relude.Base (Constraint, Eq, IO, Type, coerce, ($!))
import Relude.Bool (Bool (..), (&&^), (||^))
import Relude.Container.Reexport (HashSet, Set)
import Relude.Foldable.Reexport (Foldable (..))
import Relude.Function (flip, (.))
import Relude.Monad.Reexport (Monad (..))
import Relude.Monoid (Alt (..), Ap (..), Monoid (..), Semigroup)
import Relude.Numeric (Num (..))
import qualified Data.Foldable as F
flipfoldl' :: Foldable f => (a -> b -> b) -> b -> f a -> b
flipfoldl' :: forall (f :: * -> *) a b.
Foldable f =>
(a -> b -> b) -> b -> f a -> b
flipfoldl' a -> b -> b
f = forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (forall a b c. (a -> b -> c) -> b -> a -> c
flip a -> b -> b
f)
{-# INLINE flipfoldl' #-}
asumMap :: forall b m f a . (Foldable f, Alternative m) => (a -> m b) -> f a -> m b
asumMap :: forall b (m :: * -> *) (f :: * -> *) a.
(Foldable f, Alternative m) =>
(a -> m b) -> f a -> m b
asumMap = coerce :: forall a b. Coercible a b => a -> b
coerce (forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap :: (a -> Alt m b) -> f a -> Alt m b)
{-# INLINE asumMap #-}
foldMapA
:: forall b m f a . (Semigroup b, Monoid b, Applicative m, Foldable f)
=> (a -> m b)
-> f a
-> m b
foldMapA :: forall b (m :: * -> *) (f :: * -> *) a.
(Semigroup b, Monoid b, Applicative m, Foldable f) =>
(a -> m b) -> f a -> m b
foldMapA = coerce :: forall a b. Coercible a b => a -> b
coerce (forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap :: (a -> Ap m b) -> f a -> Ap m b)
{-# INLINE foldMapA #-}
foldMapM :: forall b m f a . (Monoid b, Monad m, Foldable f) => (a -> m b) -> f a -> m b
foldMapM :: forall b (m :: * -> *) (f :: * -> *) a.
(Monoid b, Monad m, Foldable f) =>
(a -> m b) -> f a -> m b
foldMapM a -> m b
f f a
xs = forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr a -> (b -> m b) -> b -> m b
step forall (m :: * -> *) a. Monad m => a -> m a
return f a
xs forall a. Monoid a => a
mempty
where
step :: a -> (b -> m b) -> b -> m b
step a
x b -> m b
r b
z = a -> m b
f a
x forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \b
y -> b -> m b
r forall a b. (a -> b) -> a -> b
$! b
z forall a. Monoid a => a -> a -> a
`mappend` b
y
{-# INLINE foldMapM #-}
sum :: forall a f . (Foldable f, Num a) => f a -> a
sum :: forall a (f :: * -> *). (Foldable f, Num a) => f a -> a
sum = forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' forall a. Num a => a -> a -> a
(+) a
0
{-# INLINE sum #-}
product :: forall a f . (Foldable f, Num a) => f a -> a
product :: forall a (f :: * -> *). (Foldable f, Num a) => f a -> a
product = forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' forall a. Num a => a -> a -> a
(*) a
1
{-# INLINE product #-}
elem :: (Foldable f, DisallowElem f, Eq a) => a -> f a -> Bool
elem :: forall (f :: * -> *) a.
(Foldable f, DisallowElem f, Eq a) =>
a -> f a -> Bool
elem = forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
F.elem
{-# INLINE elem #-}
notElem :: (Foldable f, DisallowElem f, Eq a) => a -> f a -> Bool
notElem :: forall (f :: * -> *) a.
(Foldable f, DisallowElem f, Eq a) =>
a -> f a -> Bool
notElem = forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
F.notElem
{-# INLINE notElem #-}
andM :: (Foldable f, Monad m) => f (m Bool) -> m Bool
andM :: forall (f :: * -> *) (m :: * -> *).
(Foldable f, Monad m) =>
f (m Bool) -> m Bool
andM = forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr forall (m :: * -> *). Monad m => m Bool -> m Bool -> m Bool
(&&^) (forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
True)
{-# INLINE andM #-}
{-# SPECIALIZE andM :: [IO Bool] -> IO Bool #-}
orM :: (Foldable f, Monad m) => f (m Bool) -> m Bool
orM :: forall (f :: * -> *) (m :: * -> *).
(Foldable f, Monad m) =>
f (m Bool) -> m Bool
orM = forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr forall (m :: * -> *). Monad m => m Bool -> m Bool -> m Bool
(||^) (forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
False)
{-# INLINE orM #-}
{-# SPECIALIZE orM :: [IO Bool] -> IO Bool #-}
allM :: (Foldable f, Monad m) => (a -> m Bool) -> f a -> m Bool
allM :: forall (f :: * -> *) (m :: * -> *) a.
(Foldable f, Monad m) =>
(a -> m Bool) -> f a -> m Bool
allM a -> m Bool
p = forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (forall (m :: * -> *). Monad m => m Bool -> m Bool -> m Bool
(&&^) forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> m Bool
p) (forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
True)
{-# INLINE allM #-}
{-# SPECIALIZE allM :: (a -> IO Bool) -> [a] -> IO Bool #-}
anyM :: (Foldable f, Monad m) => (a -> m Bool) -> f a -> m Bool
anyM :: forall (f :: * -> *) (m :: * -> *) a.
(Foldable f, Monad m) =>
(a -> m Bool) -> f a -> m Bool
anyM a -> m Bool
p = forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (forall (m :: * -> *). Monad m => m Bool -> m Bool -> m Bool
(||^) forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> m Bool
p) (forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
False)
{-# INLINE anyM #-}
{-# SPECIALIZE anyM :: (a -> IO Bool) -> [a] -> IO Bool #-}
type family DisallowElem (f :: Type -> Type) :: Constraint where
DisallowElem Set = TypeError (ElemErrorMessage Set SetMemberType)
DisallowElem HashSet = TypeError (ElemErrorMessage HashSet HashSetMemberType)
DisallowElem f = ()
type family ElemErrorMessage (t :: k) (msg :: Symbol) :: ErrorMessage where
ElemErrorMessage t msg =
'Text "Do not use 'elem' and 'notElem' methods from 'Foldable' on " ':<>: 'ShowType t
':$$: 'Text "Suggestions:"
':$$: 'Text " Instead of"
':$$: 'Text " elem :: (Foldable t, Eq a) => a -> t a -> Bool"
':$$: 'Text " use"
':$$: 'Text " member :: " ':<>: 'Text msg
':$$: 'Text ""
':$$: 'Text " Instead of"
':$$: 'Text " notElem :: (Foldable t, Eq a) => a -> t a -> Bool"
':$$: 'Text " use"
':$$: 'Text " not . member"
':$$: 'Text ""
type SetMemberType = "Ord a => a -> Set a -> Bool"
type HashSetMemberType = "(Eq a, Hashable a) => a -> HashSet a -> Bool"