module Fold.Shortcut.Utilities where

import Fold.Shortcut.Type

import Fold.Shortcut.Run (run)
import Strict (willSave, willBoost, getVitality')

import qualified Strict

motivate :: ShortcutFold a b -> ShortcutFold a b
motivate :: forall a b. ShortcutFold a b -> ShortcutFold a b
motivate ShortcutFold{ Vitality x y
initial :: ()
initial :: 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 } =
  ShortcutFold
    { initial :: Vitality x y
initial = forall a b. Vitality a b -> Vitality a b
willBoost Vitality x y
initial
    , 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 :: ShortcutFold a b -> ShortcutFold a b
demotivate :: forall a b. ShortcutFold a b -> ShortcutFold a b
demotivate ShortcutFold{ Vitality x y
initial :: 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 } =
  ShortcutFold
    { initial :: Vitality (Either x y) y
initial = forall a b. Vitality a b -> Vitality (Either a b) b
willSave Vitality x y
initial
    , 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 :: ShortcutFold a b -> ShortcutFold a (ShortcutFold a b)
duplicate :: forall a b. ShortcutFold a b -> ShortcutFold a (ShortcutFold a b)
duplicate ShortcutFold{ Vitality x y
initial :: 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 } =
  ShortcutFold
    { Vitality x y
initial :: Vitality x y
initial :: 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
initial = Vitality x y
v, y -> a -> Vitality x y
step :: y -> a -> Vitality x y
step :: y -> a -> Vitality x y
step, Vitality x y -> b
extract :: Vitality x y -> b
extract :: Vitality x y -> b
extract }
    }

withVitality :: ShortcutFold a b -> ShortcutFold a (Vitality' b)
withVitality :: forall a b. ShortcutFold a b -> ShortcutFold a (Vitality' b)
withVitality ShortcutFold{ Vitality x y
initial :: 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 } =
  ShortcutFold
    { Vitality x y
initial :: Vitality x y
initial :: 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 fold for a single item (@x@) into a fold for lists
    of items (@xs@) -}
repeatedly :: forall x xs result.
    (forall b. ShortcutFold x b -> xs -> b)
        -- ^ A witness to the fact that @xs@ is a list of @x@
    -> ShortcutFold x result
    -> ShortcutFold xs result
repeatedly :: forall x xs result.
(forall b. ShortcutFold x b -> xs -> b)
-> ShortcutFold x result -> ShortcutFold xs result
repeatedly forall b. ShortcutFold x b -> xs -> b
runXs ShortcutFold x result
foldX =
  ShortcutFold
    { initial :: Vitality (ShortcutFold x result) (ShortcutFold x result)
initial = forall a b. ShortcutFold a b -> [a] -> b
run (forall a b. ShortcutFold a b -> ShortcutFold a (Vitality' b)
withVitality (forall a b. ShortcutFold a b -> ShortcutFold a (ShortcutFold a b)
duplicate ShortcutFold x result
foldX)) []
    , step :: ShortcutFold x result
-> xs -> Vitality (ShortcutFold x result) (ShortcutFold x result)
step = \ShortcutFold x result
f xs
xs -> forall b. ShortcutFold x b -> xs -> b
runXs (forall a b. ShortcutFold a b -> ShortcutFold a (Vitality' b)
withVitality (forall a b. ShortcutFold a b -> ShortcutFold a (ShortcutFold a b)
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
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) -> ShortcutFold b r -> ShortcutFold a r
premap :: forall a b r. (a -> b) -> ShortcutFold b r -> ShortcutFold a r
premap a -> b
f ShortcutFold{ Vitality x y
initial :: 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 } =
    ShortcutFold{ Vitality x y
initial :: Vitality x y
initial :: Vitality x y
initial, 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 }