module Fold.ShortcutNonempty.Utilities where

import Fold.ShortcutNonempty.Type

import Fold.Shortcut.Type (ShortcutFold (ShortcutFold))
import Strict (willSave, willBoost, getVitality')

import qualified Strict
import qualified Fold.Shortcut.Type as Empty
import qualified Fold.Shortcut.Utilities as Empty
import qualified Fold.Shortcut.Run as Empty (run)
import qualified Fold.ShortcutNonempty.Conversion as Nonempty

motivate :: ShortcutNonemptyFold a b -> ShortcutNonemptyFold a b
motivate :: forall a b. ShortcutNonemptyFold a b -> ShortcutNonemptyFold a b
motivate ShortcutNonemptyFold{ a -> Vitality x y
initial :: ()
initial :: a -> Vitality x y
initial, y -> a -> Vitality x y
step :: ()
step :: y -> a -> Vitality x y
step, Vitality x y -> b
extract :: ()
extract :: Vitality x y -> b
extract } =
  ShortcutNonemptyFold
    { initial :: a -> Vitality x y
initial = \a
a -> forall a b. Vitality a b -> Vitality a b
willBoost (a -> Vitality x y
initial a
a)
    , step :: y -> a -> Vitality x y
step = \y
x a
a -> forall a b. Vitality a b -> Vitality a b
willBoost (y -> a -> Vitality x y
step y
x a
a)
    , Vitality x y -> b
extract :: Vitality x y -> b
extract :: Vitality x y -> b
extract
    }

{-| Causes a shortcut fold to stop once it becomes ambivalent -}
demotivate :: ShortcutNonemptyFold a b -> ShortcutNonemptyFold a b
demotivate :: forall a b. ShortcutNonemptyFold a b -> ShortcutNonemptyFold a b
demotivate ShortcutNonemptyFold{ a -> Vitality x y
initial :: a -> Vitality x y
initial :: ()
initial, y -> a -> Vitality x y
step :: y -> a -> Vitality x y
step :: ()
step, Vitality x y -> b
extract :: Vitality x y -> b
extract :: ()
extract } =
  ShortcutNonemptyFold
    { initial :: a -> Vitality (Either x y) y
initial = \a
a -> forall a b. Vitality a b -> Vitality (Either a b) b
willSave (a -> Vitality x y
initial a
a)
    , step :: y -> a -> Vitality (Either x y) y
step = \y
x a
a -> forall a b. Vitality a b -> Vitality (Either a b) b
willSave (y -> a -> Vitality x y
step y
x a
a)
    , extract :: Vitality (Either x y) y -> b
extract = \Vitality (Either x y) y
v -> case Vitality (Either x y) y
v of
        Dead Either x y
e -> case Either x y
e of
          Strict.Left x
x -> Vitality x y -> b
extract (forall a b. a -> Vitality a b
Dead x
x)
          Strict.Right y
x -> Vitality x y -> b
extract (forall a b. Will -> b -> Vitality a b
Alive Will
Ambivalent y
x)
        Alive Will
w y
x -> Vitality x y -> b
extract (forall a b. Will -> b -> Vitality a b
Alive Will
w y
x)
    }

{-| Allows to continue feeding a fold even after passing it to a function
    that closes it -}
duplicate :: ShortcutNonemptyFold a b -> ShortcutNonemptyFold a (ShortcutFold a b)
duplicate :: forall a b.
ShortcutNonemptyFold a b
-> ShortcutNonemptyFold a (ShortcutFold a b)
duplicate ShortcutNonemptyFold{ a -> Vitality x y
initial :: a -> Vitality x y
initial :: ()
initial, y -> a -> Vitality x y
step :: y -> a -> Vitality x y
step :: ()
step, Vitality x y -> b
extract :: Vitality x y -> b
extract :: ()
extract } =
  ShortcutNonemptyFold
    { a -> Vitality x y
initial :: a -> Vitality x y
initial :: a -> Vitality x y
initial
    , y -> a -> Vitality x y
step :: y -> a -> Vitality x y
step :: y -> a -> Vitality x y
step
    , extract :: Vitality x y -> ShortcutFold a b
extract = \Vitality x y
v -> ShortcutFold{ initial :: Vitality x y
Empty.initial = Vitality x y
v, y -> a -> Vitality x y
step :: y -> a -> Vitality x y
step :: y -> a -> Vitality x y
Empty.step, Vitality x y -> b
extract :: Vitality x y -> b
extract :: Vitality x y -> b
Empty.extract }
    }

withVitality :: ShortcutNonemptyFold a b -> ShortcutNonemptyFold a (Vitality' b)
withVitality :: forall a b.
ShortcutNonemptyFold a b -> ShortcutNonemptyFold a (Vitality' b)
withVitality ShortcutNonemptyFold{ a -> Vitality x y
initial :: a -> Vitality x y
initial :: ()
initial, y -> a -> Vitality x y
step :: y -> a -> Vitality x y
step :: ()
step, Vitality x y -> b
extract :: Vitality x y -> b
extract :: ()
extract } =
  ShortcutNonemptyFold
    { a -> Vitality x y
initial :: a -> Vitality x y
initial :: a -> Vitality x y
initial
    , y -> a -> Vitality x y
step :: y -> a -> Vitality x y
step :: y -> a -> Vitality x y
step
    , extract :: Vitality x y -> Vitality b b
extract = \Vitality x y
v -> let x :: b
x = Vitality x y -> b
extract Vitality x y
v in case Vitality x y
v of
        Alive Will
w y
_ -> forall a b. Will -> b -> Vitality a b
Alive Will
w b
x
        Dead x
_ -> forall a b. a -> Vitality a b
Dead b
x
    }

{-| Convert a nonempty fold for a single item (@x@) into a
    nonempty fold for nonempty lists of items (@xs@) -}
repeatedly :: forall x xs result.
    (forall b. ShortcutNonemptyFold x b -> xs -> b)
        -- ^ A witness to the fact that @xs@ is a nonempty list of @x@
    -> ShortcutNonemptyFold x result
    -> ShortcutNonemptyFold xs result
repeatedly :: forall x xs result.
(forall b. ShortcutNonemptyFold x b -> xs -> b)
-> ShortcutNonemptyFold x result -> ShortcutNonemptyFold xs result
repeatedly forall b. ShortcutNonemptyFold x b -> xs -> b
runXs ShortcutNonemptyFold x result
foldX =
  ShortcutNonemptyFold
    { initial :: xs -> Vitality (ShortcutFold x result) (ShortcutFold x result)
initial = \xs
xs -> forall b. ShortcutNonemptyFold x b -> xs -> b
runXs (forall a b.
ShortcutNonemptyFold a b -> ShortcutNonemptyFold a (Vitality' b)
withVitality (forall a b.
ShortcutNonemptyFold a b
-> ShortcutNonemptyFold a (ShortcutFold a b)
duplicate ShortcutNonemptyFold x result
foldX)) xs
xs
    , step :: ShortcutFold x result
-> xs -> Vitality (ShortcutFold x result) (ShortcutFold x result)
step = \ShortcutFold x result
f xs
xs -> forall b. ShortcutNonemptyFold x b -> xs -> b
runXs (forall a b.
ShortcutNonemptyFold a b -> ShortcutNonemptyFold a (Vitality' b)
withVitality (forall a b. ShortcutFold a b -> ShortcutNonemptyFold a b
Nonempty.shortcutFold (forall a b. ShortcutFold a b -> ShortcutFold a (ShortcutFold a b)
Empty.duplicate ShortcutFold x result
f))) xs
xs
    , extract :: Vitality (ShortcutFold x result) (ShortcutFold x result) -> result
extract = \Vitality (ShortcutFold x result) (ShortcutFold x result)
f -> forall a b. ShortcutFold a b -> [a] -> b
Empty.run (forall a. Vitality' a -> a
getVitality' Vitality (ShortcutFold x result) (ShortcutFold x result)
f) []
    }

{-| Applies a function to each input before processing -}
premap :: (a -> b) -> ShortcutNonemptyFold b r -> ShortcutNonemptyFold a r
premap :: forall a b r.
(a -> b) -> ShortcutNonemptyFold b r -> ShortcutNonemptyFold a r
premap a -> b
f ShortcutNonemptyFold{ b -> Vitality x y
initial :: b -> Vitality x y
initial :: ()
initial, y -> b -> Vitality x y
step :: y -> b -> Vitality x y
step :: ()
step, Vitality x y -> r
extract :: Vitality x y -> r
extract :: ()
extract } =
    ShortcutNonemptyFold{ initial :: a -> Vitality x y
initial = \a
a -> b -> Vitality x y
initial (a -> b
f a
a),
        step :: y -> a -> Vitality x y
step = \y
x a
a -> y -> b -> Vitality x y
step y
x (a -> b
f a
a), Vitality x y -> r
extract :: Vitality x y -> r
extract :: Vitality x y -> r
extract }