-- | Getting an 'EffectfulFold' from some other type of fold
module Fold.Effectful.Conversion where

import Fold.Effectful.Type

import Control.Monad (Monad)
import Data.Maybe (Maybe)
import Fold.Nonempty.Type (NonemptyFold)
import Fold.Shortcut.Type (ShortcutFold)
import Fold.ShortcutNonempty.Type (ShortcutNonemptyFold)

import qualified Control.Applicative as Applicative
import qualified Fold.Pure.Conversion as Pure
import qualified Fold.Pure.Type as Pure

{-| Generalize a pure fold to an effectful fold -}
fold :: Monad m => Pure.Fold a b -> EffectfulFold m a b
fold :: forall (m :: * -> *) a b.
Monad m =>
Fold a b -> EffectfulFold m a b
fold Pure.Fold{ x
initial :: ()
initial :: x
Pure.initial, x -> a -> x
step :: ()
step :: x -> a -> x
Pure.step, x -> b
extract :: ()
extract :: x -> b
Pure.extract } = EffectfulFold
    { initial :: m x
initial =         forall (f :: * -> *) a. Applicative f => a -> f a
Applicative.pure ( x
initial   )
    , step :: x -> a -> m x
step    = \x
x a
a -> forall (f :: * -> *) a. Applicative f => a -> f a
Applicative.pure ( x -> a -> x
step x
x a
a  )
    , extract :: x -> m b
extract = \x
x   -> forall (f :: * -> *) a. Applicative f => a -> f a
Applicative.pure ( x -> b
extract x
x )
    }

{-| Turn a nonempty fold that requires at least one input into a fold that
    returns 'Data.Maybe.Nothing' when there are no inputs -}
nonemptyFold :: Monad m => NonemptyFold a b -> EffectfulFold m a (Maybe b)
nonemptyFold :: forall (m :: * -> *) a b.
Monad m =>
NonemptyFold a b -> EffectfulFold m a (Maybe b)
nonemptyFold NonemptyFold a b
x = forall (m :: * -> *) a b.
Monad m =>
Fold a b -> EffectfulFold m a b
fold (forall a b. NonemptyFold a b -> Fold a (Maybe b)
Pure.nonemptyFold NonemptyFold a b
x)

shortcutFold :: Monad m =>  ShortcutFold a b -> EffectfulFold m a b
shortcutFold :: forall (m :: * -> *) a b.
Monad m =>
ShortcutFold a b -> EffectfulFold m a b
shortcutFold ShortcutFold a b
x = forall (m :: * -> *) a b.
Monad m =>
Fold a b -> EffectfulFold m a b
fold (forall a b. ShortcutFold a b -> Fold a b
Pure.shortcutFold ShortcutFold a b
x)

shortcutNonemptyFold :: Monad m => ShortcutNonemptyFold a b -> EffectfulFold m a (Maybe b)
shortcutNonemptyFold :: forall (m :: * -> *) a b.
Monad m =>
ShortcutNonemptyFold a b -> EffectfulFold m a (Maybe b)
shortcutNonemptyFold ShortcutNonemptyFold a b
x = forall (m :: * -> *) a b.
Monad m =>
Fold a b -> EffectfulFold m a b
fold (forall a b. ShortcutNonemptyFold a b -> Fold a (Maybe b)
Pure.shortcutNonemptyFold ShortcutNonemptyFold a b
x)