gambler-0.4.1.0: source/Fold/Effectful/Type.hs
module Fold.Effectful.Type where
import Control.Applicative (Applicative, liftA2, pure, (<*>))
import Control.Monad (Monad)
import Data.Functor (Functor, fmap, (<$>))
import Data.Monoid (Monoid, mempty)
import Data.Semigroup (Semigroup, (<>))
import Prelude (($!))
import qualified Strict
{-| Processes inputs of type @a@ and results in an effectful value of type @m b@ -}
data EffectfulFold m a b = forall x. EffectfulFold
{ initial :: m x
, step :: x -> a -> m x
, extract :: x -> m b
}
instance Functor m => Functor (EffectfulFold m a) where
fmap f EffectfulFold{ initial, step, extract } = EffectfulFold
{ initial
, step
, extract = \x -> fmap f $! extract x
}
instance Applicative m => Applicative (EffectfulFold m a) where
pure b = EffectfulFold{ initial = pure (), step = \() _ -> pure (), extract = \() -> pure b }
(<*>)
EffectfulFold{ initial = initialL, step = stepL, extract = extractL }
EffectfulFold{ initial = initialR, step = stepR, extract = extractR } =
EffectfulFold
{ initial = Strict.Tuple2 <$> initialL <*> initialR
, step = \(Strict.Tuple2 xL xR) a -> Strict.Tuple2 <$> stepL xL a <*> stepR xR a
, extract = \(Strict.Tuple2 xL xR) -> extractL xL <*> extractR xR
}
instance (Semigroup b, Monad m) => Semigroup (EffectfulFold m a b) where
(<>) = liftA2 (<>)
instance (Monoid b, Monad m) => Monoid (EffectfulFold m a b) where
mempty = pure mempty