-- | Folds from "Fold.Pure.Nonempty" trivially lifted into 'EffectfulFold'
module Fold.Effectful.Nonempty
  (
    {- * General -} magma, semigroup,
    {- * Endpoints -} first, last,
    {- * Extrema -} maximum, minimum, maximumBy, minimumBy,
  )
  where

import Control.Monad (Monad)
import Data.Maybe (Maybe)
import Data.Ord (Ord, Ordering)
import Data.Semigroup (Semigroup)
import Fold.Effectful.Conversion (fold)
import Fold.Effectful.Type (EffectfulFold)

import qualified Fold.Pure.Nonempty as Pure

{-| Start with the first input, append each new input on the right
with the given function -}
magma :: (a -> a -> a) -> Monad m => EffectfulFold m a (Maybe a)
magma :: forall a (m :: * -> *).
(a -> a -> a) -> Monad m => EffectfulFold m a (Maybe a)
magma a -> a -> a
step = forall (m :: * -> *) a b.
Monad m =>
Fold a b -> EffectfulFold m a b
fold (forall a. (a -> a -> a) -> Fold a (Maybe a)
Pure.magma a -> a -> a
step)

{-| Append each new input on the right with ('<>') -}
semigroup :: Semigroup a => Monad m => EffectfulFold m a (Maybe a)
semigroup :: forall a (m :: * -> *).
(Semigroup a, Monad m) =>
EffectfulFold m a (Maybe a)
semigroup = forall (m :: * -> *) a b.
Monad m =>
Fold a b -> EffectfulFold m a b
fold forall a. Semigroup a => Fold a (Maybe a)
Pure.semigroup

{-| The first input -}
first :: Monad m => EffectfulFold m a (Maybe a)
first :: forall (m :: * -> *) a. Monad m => EffectfulFold m a (Maybe a)
first = forall (m :: * -> *) a b.
Monad m =>
Fold a b -> EffectfulFold m a b
fold forall a. Fold a (Maybe a)
Pure.first

{-| The last input -}
last :: Monad m => EffectfulFold m a (Maybe a)
last :: forall (m :: * -> *) a. Monad m => EffectfulFold m a (Maybe a)
last = forall (m :: * -> *) a b.
Monad m =>
Fold a b -> EffectfulFold m a b
fold forall a. Fold a (Maybe a)
Pure.last

{-| The greatest input -}
maximum :: Ord a => Monad m => EffectfulFold m a (Maybe a)
maximum :: forall a (m :: * -> *).
(Ord a, Monad m) =>
EffectfulFold m a (Maybe a)
maximum = forall (m :: * -> *) a b.
Monad m =>
Fold a b -> EffectfulFold m a b
fold forall a. Ord a => Fold a (Maybe a)
Pure.maximum

{-| The greatest input with respect to the given comparison function -}
maximumBy :: (a -> a -> Ordering) -> Monad m => EffectfulFold m a (Maybe a)
maximumBy :: forall a (m :: * -> *).
(a -> a -> Ordering) -> Monad m => EffectfulFold m a (Maybe a)
maximumBy a -> a -> Ordering
cmp = forall (m :: * -> *) a b.
Monad m =>
Fold a b -> EffectfulFold m a b
fold (forall a. (a -> a -> Ordering) -> Fold a (Maybe a)
Pure.maximumBy a -> a -> Ordering
cmp)

{-| The least input -}
minimum :: Ord a => Monad m => EffectfulFold m a (Maybe a)
minimum :: forall a (m :: * -> *).
(Ord a, Monad m) =>
EffectfulFold m a (Maybe a)
minimum = forall (m :: * -> *) a b.
Monad m =>
Fold a b -> EffectfulFold m a b
fold forall a. Ord a => Fold a (Maybe a)
Pure.minimum

{-| The least input with respect to the given comparison function -}
minimumBy :: (a -> a -> Ordering) -> Monad m => EffectfulFold m a (Maybe a)
minimumBy :: forall a (m :: * -> *).
(a -> a -> Ordering) -> Monad m => EffectfulFold m a (Maybe a)
minimumBy a -> a -> Ordering
cmp = forall (m :: * -> *) a b.
Monad m =>
Fold a b -> EffectfulFold m a b
fold (forall a. (a -> a -> Ordering) -> Fold a (Maybe a)
Pure.minimumBy a -> a -> Ordering
cmp)