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

import Data.Maybe (Maybe)
import Data.Ord (Ord, Ordering)
import Data.Semigroup (Semigroup)
import Fold.Pure.Conversion (nonemptyFold)
import Fold.Pure.Type (Fold)

import qualified Fold.Nonempty.Examples as Nonempty

{-| Start with the first input, append each new input on the right
with the given function -}
magma :: (a -> a -> a) -> Fold a (Maybe a)
magma :: forall a. (a -> a -> a) -> Fold a (Maybe a)
magma a -> a -> a
step = forall a b. NonemptyFold a b -> Fold a (Maybe b)
nonemptyFold (forall a. (a -> a -> a) -> NonemptyFold a a
Nonempty.magma a -> a -> a
step)

{-| Append each new input on the right with ('<>') -}
semigroup :: Semigroup a => Fold a (Maybe a)
semigroup :: forall a. Semigroup a => Fold a (Maybe a)
semigroup = forall a b. NonemptyFold a b -> Fold a (Maybe b)
nonemptyFold forall a. Semigroup a => NonemptyFold a a
Nonempty.semigroup

{-| The first input -}
first :: Fold a (Maybe a)
first :: forall a. Fold a (Maybe a)
first = forall a b. NonemptyFold a b -> Fold a (Maybe b)
nonemptyFold forall a. NonemptyFold a a
Nonempty.first

{-| The last input -}
last :: Fold a (Maybe a)
last :: forall a. Fold a (Maybe a)
last = forall a b. NonemptyFold a b -> Fold a (Maybe b)
nonemptyFold forall a. NonemptyFold a a
Nonempty.last

{-| The greatest input -}
maximum :: Ord a => Fold a (Maybe a)
maximum :: forall a. Ord a => Fold a (Maybe a)
maximum = forall a b. NonemptyFold a b -> Fold a (Maybe b)
nonemptyFold forall a. Ord a => NonemptyFold a a
Nonempty.maximum

{-| The greatest input with respect to the given comparison function -}
maximumBy :: (a -> a -> Ordering) -> Fold a (Maybe a)
maximumBy :: forall a. (a -> a -> Ordering) -> Fold a (Maybe a)
maximumBy a -> a -> Ordering
cmp = forall a b. NonemptyFold a b -> Fold a (Maybe b)
nonemptyFold (forall a. (a -> a -> Ordering) -> NonemptyFold a a
Nonempty.maximumBy a -> a -> Ordering
cmp)

{-| The least input -}
minimum :: Ord a => Fold a (Maybe a)
minimum :: forall a. Ord a => Fold a (Maybe a)
minimum = forall a b. NonemptyFold a b -> Fold a (Maybe b)
nonemptyFold forall a. Ord a => NonemptyFold a a
Nonempty.minimum

{-| The least input with respect to the given comparison function -}
minimumBy :: (a -> a -> Ordering) -> Fold a (Maybe a)
minimumBy :: forall a. (a -> a -> Ordering) -> Fold a (Maybe a)
minimumBy a -> a -> Ordering
cmp = forall a b. NonemptyFold a b -> Fold a (Maybe b)
nonemptyFold (forall a. (a -> a -> Ordering) -> NonemptyFold a a
Nonempty.minimumBy a -> a -> Ordering
cmp)