module Next.Consumer.Examples
  (
     {- * Trivialities -} toList, run,
     {- * General folding -} foldPure, foldEffect, foldJob,
  )
  where

import Essentials
import Fold.Effectful.Type

import Fold (Fold)
import Next.Consumer.Type (ConsumerPlus)
import Next.Interface (Step (Item, End), next)
import SupplyChain (Job)

import qualified SupplyChain.Job as Job
import qualified Fold.Effectful
import qualified Fold.Pure

{-| Run the stream completely, collecting results using a
    fold that operates in the 'Job' context

See "Fold.Effectful" -}
foldJob :: forall item product action up.
    EffectfulFold (Job up action) item product
    -> ConsumerPlus up action item product
foldJob :: forall item product (action :: * -> *) (up :: * -> *).
EffectfulFold (Job up action) item product
-> ConsumerPlus up action item product
foldJob EffectfulFold{ Job up action x
initial :: ()
initial :: Job up action x
initial, x -> item -> Job up action x
step :: ()
step :: x -> item -> Job up action x
step, x -> Job up action product
extract :: ()
extract :: x -> Job up action product
extract } =
    Job up action x
initial forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= x -> Job up action x
go forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= x -> Job up action product
extract
  where
    go :: x -> Job up action x
go x
b = forall (up :: * -> *) product (action :: * -> *).
up product -> Job up action product
Job.order forall item (interface :: * -> *).
TerminableStream item interface =>
interface (Step item)
next forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
        Step item
End -> forall (f :: * -> *) a. Applicative f => a -> f a
pure x
b
        Item item
a -> x -> item -> Job up action x
step x
b item
a forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= x -> Job up action x
go

{-| Run the stream completely, collecting results using an
    effectful fold

See "Fold.Effectful" -}
foldEffect :: EffectfulFold action item product
    -> ConsumerPlus up action item product
foldEffect :: forall (action :: * -> *) item product (up :: * -> *).
EffectfulFold action item product
-> ConsumerPlus up action item product
foldEffect EffectfulFold action item product
f = forall item product (action :: * -> *) (up :: * -> *).
EffectfulFold (Job up action) item product
-> ConsumerPlus up action item product
foldJob (forall (m :: * -> *) (n :: * -> *) a b.
(forall x. m x -> n x)
-> EffectfulFold m a b -> EffectfulFold n a b
Fold.Effectful.hoist forall (action :: * -> *) product (up :: * -> *).
action product -> Job up action product
Job.perform EffectfulFold action item product
f)

{-| Run the stream completely, collecting results using a
    pure fold

See "Fold.Pure" -}
foldPure :: Fold item product
    -> ConsumerPlus up action item product
foldPure :: forall item product (up :: * -> *) (action :: * -> *).
Fold item product -> ConsumerPlus up action item product
foldPure Fold item product
f = forall item product (action :: * -> *) (up :: * -> *).
EffectfulFold (Job up action) item product
-> ConsumerPlus up action item product
foldJob (forall (m :: * -> *) a b.
Monad m =>
Fold a b -> EffectfulFold m a b
Fold.Effectful.fold Fold item product
f)

{-| Consumes all items and returns them as a list -}
toList :: forall up action item.
    ConsumerPlus up action item [item]
toList :: forall (up :: * -> *) (action :: * -> *) item.
ConsumerPlus up action item [item]
toList = forall item product (up :: * -> *) (action :: * -> *).
Fold item product -> ConsumerPlus up action item product
foldPure forall a. Fold a [a]
Fold.Pure.list

{-| Like 'toList', but discards the results -}
run :: forall up action item.
    ConsumerPlus up action item ()
run :: forall (up :: * -> *) (action :: * -> *) item.
ConsumerPlus up action item ()
run = forall item product (up :: * -> *) (action :: * -> *).
Fold item product -> ConsumerPlus up action item product
foldPure (forall (f :: * -> *) a. Applicative f => a -> f a
pure ())