{-# 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' :: (a -> b -> b) -> b -> f a -> b
flipfoldl' a -> b -> b
f = (b -> a -> b) -> b -> f a -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' ((a -> b -> b) -> b -> a -> b
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 :: (a -> m b) -> f a -> m b
asumMap = ((a -> Alt m b) -> f a -> Alt m b) -> (a -> m b) -> f a -> m b
coerce ((a -> Alt m b) -> f a -> Alt m b
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 :: (a -> m b) -> f a -> m b
foldMapA = ((a -> Ap m b) -> f a -> Ap m b) -> (a -> m b) -> f a -> m b
coerce ((a -> Ap m b) -> f a -> Ap m b
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 :: (a -> m b) -> f a -> m b
foldMapM a -> m b
f f a
xs = (a -> (b -> m b) -> b -> m b) -> (b -> m b) -> f a -> b -> m b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr a -> (b -> m b) -> b -> m b
step b -> m b
forall (m :: * -> *) a. Monad m => a -> m a
return f a
xs b
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 m b -> (b -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \b
y -> b -> m b
r (b -> m b) -> b -> m b
forall a b. (a -> b) -> a -> b
$! b
z b -> b -> b
forall a. Monoid a => a -> a -> a
`mappend` b
y
{-# INLINE foldMapM #-}
sum :: forall a f . (Foldable f, Num a) => f a -> a
sum :: f a -> a
sum = (a -> a -> a) -> a -> f a -> a
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' a -> a -> a
forall a. Num a => a -> a -> a
(+) a
0
{-# INLINE sum #-}
product :: forall a f . (Foldable f, Num a) => f a -> a
product :: f a -> a
product = (a -> a -> a) -> a -> f a -> a
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' a -> a -> a
forall a. Num a => a -> a -> a
(*) a
1
{-# INLINE product #-}
elem :: (Foldable f, DisallowElem f, Eq a) => a -> f a -> Bool
elem :: a -> f a -> Bool
elem = a -> f a -> Bool
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 :: a -> f a -> Bool
notElem = a -> f a -> Bool
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 :: f (m Bool) -> m Bool
andM = (m Bool -> m Bool -> m Bool) -> m Bool -> f (m Bool) -> m Bool
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr m Bool -> m Bool -> m Bool
forall (m :: * -> *). Monad m => m Bool -> m Bool -> m Bool
(&&^) (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 :: f (m Bool) -> m Bool
orM = (m Bool -> m Bool -> m Bool) -> m Bool -> f (m Bool) -> m Bool
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr m Bool -> m Bool -> m Bool
forall (m :: * -> *). Monad m => m Bool -> m Bool -> m Bool
(||^) (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 :: (a -> m Bool) -> f a -> m Bool
allM a -> m Bool
p = (a -> m Bool -> m Bool) -> m Bool -> f a -> m Bool
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (m Bool -> m Bool -> m Bool
forall (m :: * -> *). Monad m => m Bool -> m Bool -> m Bool
(&&^) (m Bool -> m Bool -> m Bool)
-> (a -> m Bool) -> a -> m Bool -> m Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> m Bool
p) (Bool -> m Bool
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 :: (a -> m Bool) -> f a -> m Bool
anyM a -> m Bool
p = (a -> m Bool -> m Bool) -> m Bool -> f a -> m Bool
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (m Bool -> m Bool -> m Bool
forall (m :: * -> *). Monad m => m Bool -> m Bool -> m Bool
(||^) (m Bool -> m Bool -> m Bool)
-> (a -> m Bool) -> a -> m Bool -> m Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> m Bool
p) (Bool -> m Bool
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"