packages feed

gambler-0.4.1.0: source/Fold/ShortcutNonempty/Utilities.hs

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 ShortcutNonemptyFold{ initial, step, extract } =
  ShortcutNonemptyFold
    { initial = \a -> willBoost (initial a)
    , step = \x a -> willBoost (step x a)
    , extract
    }

{-| Causes a shortcut fold to stop once it becomes ambivalent -}
demotivate :: ShortcutNonemptyFold a b -> ShortcutNonemptyFold a b
demotivate ShortcutNonemptyFold{ initial, step, extract } =
  ShortcutNonemptyFold
    { initial = \a -> willSave (initial a)
    , step = \x a -> willSave (step x a)
    , extract = \v -> case v of
        Dead e -> case e of
          Strict.Left x -> extract (Dead x)
          Strict.Right x -> extract (Alive Ambivalent x)
        Alive w x -> extract (Alive w 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 ShortcutNonemptyFold{ initial, step, extract } =
  ShortcutNonemptyFold
    { initial
    , step
    , extract = \v -> ShortcutFold{ Empty.initial = v, Empty.step, Empty.extract }
    }

withVitality :: ShortcutNonemptyFold a b -> ShortcutNonemptyFold a (Vitality' b)
withVitality ShortcutNonemptyFold{ initial, step, extract } =
  ShortcutNonemptyFold
    { initial
    , step
    , extract = \v -> let x = extract v in case v of
        Alive w _ -> Alive w x
        Dead _ -> Dead 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 runXs foldX =
  ShortcutNonemptyFold
    { initial = \xs -> runXs (withVitality (duplicate foldX)) xs
    , step = \f xs -> runXs (withVitality (Nonempty.shortcutFold (Empty.duplicate f))) xs
    , extract = \f -> Empty.run (getVitality' f) []
    }

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