-- | Getting a 'NonemptyFold' from some other type of fold
module Fold.Nonempty.Conversion where

import Fold.Nonempty.Type

import Fold.Effectful.Type (EffectfulFold)
import Fold.Pure.Type (Fold (Fold))
import Fold.ShortcutNonempty.Type (ShortcutNonemptyFold (ShortcutNonemptyFold))
import Fold.Shortcut.Type (ShortcutFold)
import Strict (Vitality (Dead, Alive))
import Data.Functor.Identity (Identity)

import qualified Fold.Pure.Type as Fold
import qualified Fold.Pure.Conversion as Fold.Conversion
import qualified Fold.ShortcutNonempty.Type as ShortcutNonempty

{-| Turn a regular fold that allows empty input into a fold that
requires at least one input -}
fold :: Fold a b -> NonemptyFold a b
fold :: forall a b. Fold a b -> NonemptyFold a b
fold Fold{ x
initial :: ()
initial :: x
Fold.initial, x -> a -> x
step :: ()
step :: x -> a -> x
Fold.step, x -> b
extract :: ()
extract :: x -> b
Fold.extract } =
    NonemptyFold{ initial :: a -> x
initial = x -> a -> x
step x
initial, x -> a -> x
step :: x -> a -> x
step :: x -> a -> x
step, x -> b
extract :: x -> b
extract :: x -> b
extract }

{-| Turn an effectful fold into a pure fold that requires at least
one input -}
effectfulFold :: EffectfulFold Identity a b -> NonemptyFold a b
effectfulFold :: forall a b. EffectfulFold Identity a b -> NonemptyFold a b
effectfulFold EffectfulFold Identity a b
x = forall a b. Fold a b -> NonemptyFold a b
fold (forall a b. EffectfulFold Identity a b -> Fold a b
Fold.Conversion.effectfulFold EffectfulFold Identity a b
x)

shortcutFold :: ShortcutFold a b -> NonemptyFold a b
shortcutFold :: forall a b. ShortcutFold a b -> NonemptyFold a b
shortcutFold ShortcutFold a b
x = forall a b. Fold a b -> NonemptyFold a b
fold (forall a b. ShortcutFold a b -> Fold a b
Fold.Conversion.shortcutFold ShortcutFold a b
x)

shortcutNonemptyFold :: ShortcutNonemptyFold a b -> NonemptyFold a b
shortcutNonemptyFold :: forall a b. ShortcutNonemptyFold a b -> NonemptyFold a b
shortcutNonemptyFold ShortcutNonemptyFold{ y -> a -> Vitality x y
step :: ()
step :: y -> a -> Vitality x y
ShortcutNonempty.step,
        a -> Vitality x y
initial :: ()
initial :: a -> Vitality x y
ShortcutNonempty.initial, x -> b
extractDead :: ()
extractDead :: x -> b
ShortcutNonempty.extractDead, y -> b
extractLive :: ()
extractLive :: y -> b
ShortcutNonempty.extractLive } =
    NonemptyFold
      { initial :: a -> Vitality x y
initial = a -> Vitality x y
initial
      , step :: Vitality x y -> a -> Vitality x y
step = \Vitality x y
s -> case Vitality x y
s of { Dead x
_ -> \a
_ -> Vitality x y
s; Alive Will
_ y
x -> y -> a -> Vitality x y
step y
x }
      , extract :: Vitality x y -> b
extract = \Vitality x y
s -> case Vitality x y
s of
            Dead x
x -> x -> b
extractDead x
x
            Alive Will
_ y
x -> y -> b
extractLive y
x
      }