packages feed

automaton-1.3: src/Data/Automaton/Trans/Writer.hs

{- | An 'Automaton' with a 'WriterT' layer outputs an extra monoid value on every step.

It is based on the /strict/ writer monad 'Control.Monad.Trans.Writer.Strict',
so when combining it with other modules such as @mtl@'s,
the strict version has to be included, i.e. 'Control.Monad.Writer.Strict'
instead of 'Control.Monad.Writer' or 'Control.Monad.Writer.Lazy'.
-}
module Data.Automaton.Trans.Writer (
  module Control.Monad.Trans.Writer.Strict,
  writerS,
  runWriterS,
)
where

-- transformers
import Control.Monad.Trans.Writer.Strict hiding (liftCallCC, liftCatch, pass)

-- automaton
import Data.Automaton (Automaton, withAutomaton)
import Data.Stream.Result (Result (Result))

{- | Convert an extra log output into a 'WriterT' effect.

This is the opposite of 'runWriterS'.
-}
writerS ::
  (Functor m, Monad m, Monoid w) =>
  Automaton m a (w, b) ->
  Automaton (WriterT w m) a b
writerS = withAutomaton $ \f a -> WriterT $ (\(Result s (w, b)) -> (Result s b, w)) <$> f a

{- | Convert a 'WriterT' effect into an extra log output.

This is the opposite of 'writerS'.
-}
runWriterS ::
  (Functor m, Monad m) =>
  Automaton (WriterT w m) a b ->
  Automaton m a (w, b)
runWriterS = withAutomaton $ \f a ->
  (\(Result s b, w) -> Result s (w, b))
    <$> runWriterT (f a)