{- | 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 :: forall (m :: Type -> Type) r a b.
Monad m =>
Automaton m (r, a) b -> Automaton (ReaderT r m) a b
readerS = (forall s.
 ((r, a) -> m (Result s b)) -> a -> ReaderT r m (Result s b))
-> Automaton m (r, a) b -> Automaton (ReaderT r m) a b
forall (m1 :: Type -> Type) (m2 :: Type -> Type) a1 b1 a2 b2.
(Functor m1, Functor m2) =>
(forall s. (a1 -> m1 (Result s b1)) -> a2 -> m2 (Result s b2))
-> Automaton m1 a1 b1 -> Automaton m2 a2 b2
withAutomaton ((forall s.
  ((r, a) -> m (Result s b)) -> a -> ReaderT r m (Result s b))
 -> Automaton m (r, a) b -> Automaton (ReaderT r m) a b)
-> (forall s.
    ((r, a) -> m (Result s b)) -> a -> ReaderT r m (Result s b))
-> Automaton m (r, a) b
-> Automaton (ReaderT r m) a b
forall a b. (a -> b) -> a -> b
$ \(r, a) -> m (Result s b)
f a
a -> (r -> m (Result s b)) -> ReaderT r m (Result s b)
forall r (m :: Type -> Type) a. (r -> m a) -> ReaderT r m a
ReaderT ((r -> m (Result s b)) -> ReaderT r m (Result s b))
-> (r -> m (Result s b)) -> ReaderT r m (Result s b)
forall a b. (a -> b) -> a -> b
$ \r
r -> (r, a) -> m (Result s b)
f (r
r, a
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 :: forall (m :: Type -> Type) r a b.
Monad m =>
Automaton (ReaderT r m) a b -> Automaton m (r, a) b
runReaderS = (forall s.
 (a -> ReaderT r m (Result s b)) -> (r, a) -> m (Result s b))
-> Automaton (ReaderT r m) a b -> Automaton m (r, a) b
forall (m1 :: Type -> Type) (m2 :: Type -> Type) a1 b1 a2 b2.
(Functor m1, Functor m2) =>
(forall s. (a1 -> m1 (Result s b1)) -> a2 -> m2 (Result s b2))
-> Automaton m1 a1 b1 -> Automaton m2 a2 b2
withAutomaton ((forall s.
  (a -> ReaderT r m (Result s b)) -> (r, a) -> m (Result s b))
 -> Automaton (ReaderT r m) a b -> Automaton m (r, a) b)
-> (forall s.
    (a -> ReaderT r m (Result s b)) -> (r, a) -> m (Result s b))
-> Automaton (ReaderT r m) a b
-> Automaton m (r, a) b
forall a b. (a -> b) -> a -> b
$ \a -> ReaderT r m (Result s b)
f (r
r, a
a) -> ReaderT r m (Result s b) -> r -> m (Result s b)
forall r (m :: Type -> Type) a. ReaderT r m a -> r -> m a
runReaderT (a -> ReaderT r m (Result s b)
f a
a) r
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_ :: forall (m :: Type -> Type) s a b.
Monad m =>
Automaton (ReaderT s m) a b -> s -> Automaton m a b
runReaderS_ Automaton (ReaderT s m) a b
automaton s
s = (a -> (s, a)) -> Automaton m a (s, a)
forall b c. (b -> c) -> Automaton m b c
forall (a :: Type -> Type -> Type) b c.
Arrow a =>
(b -> c) -> a b c
arr (s
s,) Automaton m a (s, a) -> Automaton m (s, a) b -> Automaton m a b
forall {k} (cat :: k -> k -> Type) (a :: k) (b :: k) (c :: k).
Category cat =>
cat a b -> cat b c -> cat a c
>>> Automaton (ReaderT s m) a b -> Automaton m (s, a) b
forall (m :: Type -> Type) r a b.
Monad m =>
Automaton (ReaderT r m) a b -> Automaton m (r, a) b
runReaderS Automaton (ReaderT s m) a b
automaton
{-# INLINE runReaderS_ #-}