-- | Folds of other types trivially lifted into 'ShortcutNonempty'
module Fold.ShortcutNonempty.Examples.Boring
  (
    {- * Search -} element, notElement, find, lookup,
    {- * Arithmetic folds -} sum, product, mean, variance, standardDeviation,
    {- * Working with indices -} index, findIndex, elementIndex,
    {- * Counting inputs -} length,
    {- * Boolean folds -} and, or, all, any,
    {- * Min/max -} maximum, minimum, maximumBy, minimumBy,
    {- * First/last -} last,
    {- * General folds -} magma, semigroup, monoid,
    {- * List folds -} list, reverseList,
  )
  where

import Data.Maybe (Maybe)
import Fold.ShortcutNonempty.Type (ShortcutNonemptyFold)
import Data.Semigroup (Semigroup)
import Data.Ord (Ord, Ordering)
import Data.Monoid (Monoid)
import Prelude (Floating, Fractional, Num)
import Data.Bool (Bool)
import Data.Eq (Eq)
import Numeric.Natural (Natural)

import qualified Fold.Shortcut.Examples.Interesting as Shortcut
import qualified Fold.Nonempty.Examples.Interesting as Nonempty
import qualified Fold.Pure.Examples.Interesting as Pure
import qualified Fold.ShortcutNonempty.Conversion as Convert

{-| Start with 'mempty', append each input on the right
    with '<>' (ambivalent) -}
monoid :: Monoid a => ShortcutNonemptyFold a a
monoid :: forall a. Monoid a => ShortcutNonemptyFold a a
monoid = forall a b. Fold a b -> ShortcutNonemptyFold a b
Convert.fold forall a. Monoid a => Fold a a
Pure.monoid

{-| The number of inputs (ambivalent) -}
length :: ShortcutNonemptyFold a Natural
length :: forall a. ShortcutNonemptyFold a Natural
length = forall a b. Fold a b -> ShortcutNonemptyFold a b
Convert.fold forall a. Fold a Natural
Pure.length

{-| 'True' if all inputs are 'True' (tenacious) -}
and :: ShortcutNonemptyFold Bool Bool
and :: ShortcutNonemptyFold Bool Bool
and = forall a b. ShortcutFold a b -> ShortcutNonemptyFold a b
Convert.shortcutFold ShortcutFold Bool Bool
Shortcut.and

{-| 'True' if any input is 'True' (tenacious) -}
or :: ShortcutNonemptyFold Bool Bool
or :: ShortcutNonemptyFold Bool Bool
or = forall a b. ShortcutFold a b -> ShortcutNonemptyFold a b
Convert.shortcutFold ShortcutFold Bool Bool
Shortcut.or

{-| 'True' if all inputs satisfy the predicate (tenacious) -}
all :: (a -> Bool) -> ShortcutNonemptyFold a Bool
all :: forall a. (a -> Bool) -> ShortcutNonemptyFold a Bool
all a -> Bool
predicate = forall a b. ShortcutFold a b -> ShortcutNonemptyFold a b
Convert.shortcutFold (forall a. (a -> Bool) -> ShortcutFold a Bool
Shortcut.all a -> Bool
predicate)

{-| 'True' if any input satisfies the predicate (tenacious) -}
any :: (a -> Bool) -> ShortcutNonemptyFold a Bool
any :: forall a. (a -> Bool) -> ShortcutNonemptyFold a Bool
any a -> Bool
predicate = forall a b. ShortcutFold a b -> ShortcutNonemptyFold a b
Convert.shortcutFold (forall a. (a -> Bool) -> ShortcutFold a Bool
Shortcut.any a -> Bool
predicate)

{-| Adds the inputs (ambivalent) -}
sum :: Num a => ShortcutNonemptyFold a a
sum :: forall a. Num a => ShortcutNonemptyFold a a
sum = forall a b. Fold a b -> ShortcutNonemptyFold a b
Convert.fold forall a. Num a => Fold a a
Pure.sum

{-| Multiplies the inputs (ambivalent) -}
product :: Num a => ShortcutNonemptyFold a a
product :: forall a. Num a => ShortcutNonemptyFold a a
product = forall a b. Fold a b -> ShortcutNonemptyFold a b
Convert.fold forall a. Num a => Fold a a
Pure.product

{-| Numerically stable arithmetic mean of the inputs (ambivalent) -}
mean :: Fractional a => ShortcutNonemptyFold a a
mean :: forall a. Fractional a => ShortcutNonemptyFold a a
mean = forall a b. Fold a b -> ShortcutNonemptyFold a b
Convert.fold forall a. Fractional a => Fold a a
Pure.mean

{-| Numerically stable (population) variance over the
    inputs (ambivalent) -}
variance :: Fractional a => ShortcutNonemptyFold a a
variance :: forall a. Fractional a => ShortcutNonemptyFold a a
variance = forall a b. Fold a b -> ShortcutNonemptyFold a b
Convert.fold forall a. Fractional a => Fold a a
Pure.variance

{-| Numerically stable (population) standard deviation over
    the inputs (ambivalent) -}
standardDeviation :: Floating a => ShortcutNonemptyFold a a
standardDeviation :: forall a. Floating a => ShortcutNonemptyFold a a
standardDeviation = forall a b. Fold a b -> ShortcutNonemptyFold a b
Convert.fold forall a. Floating a => Fold a a
Pure.standardDeviation

{-| 'True' if any input is equal to the given value (tenacious) -}
element :: Eq a => a -> ShortcutNonemptyFold a Bool
element :: forall a. Eq a => a -> ShortcutNonemptyFold a Bool
element a
a = forall a b. ShortcutFold a b -> ShortcutNonemptyFold a b
Convert.shortcutFold (forall a. Eq a => a -> ShortcutFold a Bool
Shortcut.element a
a)

{-| 'False' if any input is equal to the given value (tenacious) -}
notElement :: Eq a => a -> ShortcutNonemptyFold a Bool
notElement :: forall a. Eq a => a -> ShortcutNonemptyFold a Bool
notElement a
a = forall a b. ShortcutFold a b -> ShortcutNonemptyFold a b
Convert.shortcutFold (forall a. Eq a => a -> ShortcutFold a Bool
Shortcut.notElement a
a)

{-| The first input that satisfies the predicate, if any (tenacious) -}
find :: (a -> Bool) -> ShortcutNonemptyFold a (Maybe a)
find :: forall a. (a -> Bool) -> ShortcutNonemptyFold a (Maybe a)
find a -> Bool
ok = forall a b. ShortcutFold a b -> ShortcutNonemptyFold a b
Convert.shortcutFold (forall a. (a -> Bool) -> ShortcutFold a (Maybe a)
Shortcut.find a -> Bool
ok)

{-| The /n/th input, where n=0 is the first input, if the index
    is in bounds (tenacious) -}
index :: Natural -> ShortcutNonemptyFold a (Maybe a)
index :: forall a. Natural -> ShortcutNonemptyFold a (Maybe a)
index Natural
i = forall a b. ShortcutFold a b -> ShortcutNonemptyFold a b
Convert.shortcutFold (forall a. Natural -> ShortcutFold a (Maybe a)
Shortcut.index Natural
i)

{-| The index of the first input that matches the given value,
    if any (tenacious) -}
elementIndex :: Eq a => a -> ShortcutNonemptyFold a (Maybe Natural)
elementIndex :: forall a. Eq a => a -> ShortcutNonemptyFold a (Maybe Natural)
elementIndex a
a = forall a b. ShortcutFold a b -> ShortcutNonemptyFold a b
Convert.shortcutFold (forall a. Eq a => a -> ShortcutFold a (Maybe Natural)
Shortcut.elementIndex a
a)

{-| The index of the first input that satisfies the predicate,
    if any (tenacious) -}
findIndex :: (a -> Bool) -> ShortcutNonemptyFold a (Maybe Natural)
findIndex :: forall a. (a -> Bool) -> ShortcutNonemptyFold a (Maybe Natural)
findIndex a -> Bool
ok = forall a b. ShortcutFold a b -> ShortcutNonemptyFold a b
Convert.shortcutFold (forall a. (a -> Bool) -> ShortcutFold a (Maybe Natural)
Shortcut.findIndex a -> Bool
ok)

{-| The @b@ from the first tuple where @a@ equals the given value,
    if any (tenacious) -}
lookup :: Eq a => a -> ShortcutNonemptyFold (a, b) (Maybe b)
lookup :: forall a b. Eq a => a -> ShortcutNonemptyFold (a, b) (Maybe b)
lookup a
a = forall a b. ShortcutFold a b -> ShortcutNonemptyFold a b
Convert.shortcutFold (forall a b. Eq a => a -> ShortcutFold (a, b) (Maybe b)
Shortcut.lookup a
a)

{-| All the inputs (ambivalent) -}
list :: ShortcutNonemptyFold a [a]
list :: forall a. ShortcutNonemptyFold a [a]
list = forall a b. Fold a b -> ShortcutNonemptyFold a b
Convert.fold forall a. Fold a [a]
Pure.list

{-| All the inputs in reverse order (ambivalent) -}
reverseList :: ShortcutNonemptyFold a [a]
reverseList :: forall a. ShortcutNonemptyFold a [a]
reverseList = forall a b. Fold a b -> ShortcutNonemptyFold a b
Convert.fold forall a. Fold a [a]
Pure.reverseList

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

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

{-| The last input  (ambivalent) -}
last :: ShortcutNonemptyFold a a
last :: forall a. ShortcutNonemptyFold a a
last = forall a b. NonemptyFold a b -> ShortcutNonemptyFold a b
Convert.nonemptyFold forall a. NonemptyFold a a
Nonempty.last

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

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

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

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