packages feed

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

{- | An 'Automaton' with a 'ReaderT' layer has an extra input.

This module converts between explicit automata inputs and implicit 'ReaderT' inputs.
-}
module Data.Automaton.Trans.Reader (
  module Control.Monad.Trans.Reader,
  readerS,
  runReaderS,
  runReaderS_,
)
where

-- base
import Control.Arrow (arr, (>>>))

-- transformers
import Control.Monad.Trans.Reader

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

-- * Reader 'Automaton' running and wrapping

{- | Convert an explicit 'Automaton' input into an environment in the 'ReaderT' monad transformer.

This is the opposite of 'runReaderS'.
-}
readerS :: (Monad m) => Automaton m (r, a) b -> Automaton (ReaderT r m) a b
readerS = withAutomaton $ \f a -> ReaderT $ \r -> f (r, a)
{-# INLINE readerS #-}

{- | Convert an implicit 'ReaderT' environment into an explicit 'Automaton' input.

This is the opposite of 'readerS'.
-}
runReaderS :: (Monad m) => Automaton (ReaderT r m) a b -> Automaton m (r, a) b
runReaderS = withAutomaton $ \f (r, a) -> runReaderT (f a) r
{-# INLINE runReaderS #-}

-- | Eliminate a 'ReaderT' layer by providing its environment statically.
runReaderS_ :: (Monad m) => Automaton (ReaderT s m) a b -> s -> Automaton m a b
runReaderS_ automaton s = arr (s,) >>> runReaderS automaton
{-# INLINE runReaderS_ #-}