module Fold.ShortcutNonempty.Type
  (
    ShortcutNonemptyFold (..),
    Will (..), Vitality (..), Vitality',
  )
  where

import Control.Applicative (Applicative, liftA2, pure, (<*>))
import Data.Functor (Functor, fmap)
import Data.Monoid (Monoid, mempty)
import Data.Semigroup (Semigroup, (<>))
import Strict (Will (..), Vitality (..), Vitality')
import Data.Void (absurd)

import qualified Strict

{-| Processes at least one input of type @a@, has the ability to halt
    midway through the stream, and results in a value of type @b@ -}
data ShortcutNonemptyFold a b = forall x y. ShortcutNonemptyFold
    { ()
initial :: a -> Vitality x y
    , ()
step :: y -> a -> Vitality x y
    , ()
extract :: Vitality x y -> b
    }

instance Functor (ShortcutNonemptyFold a) where
    fmap :: forall a b.
(a -> b) -> ShortcutNonemptyFold a a -> ShortcutNonemptyFold a b
fmap a -> b
f ShortcutNonemptyFold{ y -> a -> Vitality x y
step :: y -> a -> Vitality x y
step :: ()
step, a -> Vitality x y
initial :: a -> Vitality x y
initial :: ()
initial, Vitality x y -> a
extract :: Vitality x y -> a
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 -> b
extract = \Vitality x y
x -> a -> b
f (Vitality x y -> a
extract Vitality x y
x) }

instance Applicative (ShortcutNonemptyFold a) where
    pure :: forall a. a -> ShortcutNonemptyFold a a
pure a
b = ShortcutNonemptyFold
        { initial :: a -> Vitality () Void
initial = \a
_ -> forall a b. a -> Vitality a b
Dead ()
        , step :: Void -> a -> Vitality () Void
step = forall a. Void -> a
absurd
        , extract :: Vitality () Void -> a
extract = \Vitality () Void
e -> case Vitality () Void
e of { Dead () -> a
b }
        }

    <*> :: forall a b.
ShortcutNonemptyFold a (a -> b)
-> ShortcutNonemptyFold a a -> ShortcutNonemptyFold a b
(<*>)
        ShortcutNonemptyFold{ initial :: ()
initial = a -> Vitality x y
initialL, step :: ()
step = y -> a -> Vitality x y
stepL, extract :: ()
extract = Vitality x y -> a -> b
extractL }
        ShortcutNonemptyFold{ initial :: ()
initial = a -> Vitality x y
initialR, step :: ()
step = y -> a -> Vitality x y
stepR, extract :: ()
extract = Vitality x y -> a
extractR } =
          ShortcutNonemptyFold
            { initial :: a
-> Vitality
     (Tuple2 (Vitality x y) (Vitality x y))
     (Tuple2 (Vitality x y) (Vitality x y))
initial = \a
a -> forall a1 b1 a2 b2.
Vitality a1 b1
-> Vitality a2 b2
-> Vitality' (Tuple2 (Vitality a1 b1) (Vitality a2 b2))
Strict.vitality2 (a -> Vitality x y
initialL a
a) (a -> Vitality x y
initialR a
a)
            , step :: Tuple2 (Vitality x y) (Vitality x y)
-> a
-> Vitality
     (Tuple2 (Vitality x y) (Vitality x y))
     (Tuple2 (Vitality x y) (Vitality x y))
step = \(Strict.Tuple2 Vitality x y
xL Vitality x y
xR) a
a -> forall a1 b1 a2 b2.
Vitality a1 b1
-> Vitality a2 b2
-> Vitality' (Tuple2 (Vitality a1 b1) (Vitality a2 b2))
Strict.vitality2
                (forall b a. (b -> Vitality a b) -> Vitality a b -> Vitality a b
Strict.unlessDead (\y
x -> y -> a -> Vitality x y
stepL y
x a
a) Vitality x y
xL)
                (forall b a. (b -> Vitality a b) -> Vitality a b -> Vitality a b
Strict.unlessDead (\y
x -> y -> a -> Vitality x y
stepR y
x a
a) Vitality x y
xR)
            , extract :: Vitality
  (Tuple2 (Vitality x y) (Vitality x y))
  (Tuple2 (Vitality x y) (Vitality x y))
-> b
extract = \Vitality
  (Tuple2 (Vitality x y) (Vitality x y))
  (Tuple2 (Vitality x y) (Vitality x y))
e -> case Vitality
  (Tuple2 (Vitality x y) (Vitality x y))
  (Tuple2 (Vitality x y) (Vitality x y))
e of { Dead Tuple2 (Vitality x y) (Vitality x y)
x -> Tuple2 (Vitality x y) (Vitality x y) -> b
ex Tuple2 (Vitality x y) (Vitality x y)
x; Alive Will
_ Tuple2 (Vitality x y) (Vitality x y)
x -> Tuple2 (Vitality x y) (Vitality x y) -> b
ex Tuple2 (Vitality x y) (Vitality x y)
x }
            }
          where
            ex :: Tuple2 (Vitality x y) (Vitality x y) -> b
ex (Strict.Tuple2 Vitality x y
xL Vitality x y
xR) = (Vitality x y -> a -> b
extractL Vitality x y
xL) (Vitality x y -> a
extractR Vitality x y
xR)

instance Semigroup b => Semigroup (ShortcutNonemptyFold a b) where
    <> :: ShortcutNonemptyFold a b
-> ShortcutNonemptyFold a b -> ShortcutNonemptyFold a b
(<>) = forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 forall a. Semigroup a => a -> a -> a
(<>)

instance Monoid b => Monoid (ShortcutNonemptyFold a b) where
    mempty :: ShortcutNonemptyFold a b
mempty = forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a. Monoid a => a
mempty