-- |
-- Copyright  : (c) Ivan Perez and Manuel Baerenz, 2016
-- License    : BSD3
-- Maintainer : ivan.perez@keera.co.uk
--
-- 'MSF's with a 'Reader' monadic layer.
--
-- This module contains functions to work with 'MSF's that include a 'Reader'
-- monadic layer. This includes functions to create new 'MSF's that include an
-- additional layer, and functions to flatten that layer out of the 'MSF`'s
-- transformer stack.
module Control.Monad.Trans.MSF.Reader
    ( module Control.Monad.Trans.Reader
    -- * 'Reader' 'MSF' running and wrapping.
    , readerS
    , runReaderS
    , runReaderS_
    )
  where

-- External imports
import Control.Arrow              (arr, (>>>))
import Control.Monad.Trans.Reader hiding (liftCallCC, liftCatch)

-- Internal imports
import Data.MonadicStreamFunction (MSF, morphGS)

-- * Reader 'MSF' running and wrapping

-- | Build an 'MSF' in the 'Reader' monad from one that takes the reader
-- environment as an extra input. This is the opposite of 'runReaderS'.
readerS :: Monad m => MSF m (r, a) b -> MSF (ReaderT r m) a b
readerS :: MSF m (r, a) b -> MSF (ReaderT r m) a b
readerS = (forall c. ((r, a) -> m (b, c)) -> a -> ReaderT r m (b, c))
-> MSF m (r, a) b -> MSF (ReaderT r m) a b
forall (m2 :: * -> *) a1 (m1 :: * -> *) b1 a2 b2.
Monad m2 =>
(forall c. (a1 -> m1 (b1, c)) -> a2 -> m2 (b2, c))
-> MSF m1 a1 b1 -> MSF m2 a2 b2
morphGS ((forall c. ((r, a) -> m (b, c)) -> a -> ReaderT r m (b, c))
 -> MSF m (r, a) b -> MSF (ReaderT r m) a b)
-> (forall c. ((r, a) -> m (b, c)) -> a -> ReaderT r m (b, c))
-> MSF m (r, a) b
-> MSF (ReaderT r m) a b
forall a b. (a -> b) -> a -> b
$ \(r, a) -> m (b, c)
f a
a -> (r -> m (b, c)) -> ReaderT r m (b, c)
forall r (m :: * -> *) a. (r -> m a) -> ReaderT r m a
ReaderT ((r -> m (b, c)) -> ReaderT r m (b, c))
-> (r -> m (b, c)) -> ReaderT r m (b, c)
forall a b. (a -> b) -> a -> b
$ \r
r -> (r, a) -> m (b, c)
f (r
r, a
a)

-- | Build an 'MSF' that takes an environment as an extra input from one on the
-- 'Reader' monad. This is the opposite of 'readerS'.
runReaderS :: Monad m => MSF (ReaderT r m) a b -> MSF m (r, a) b
runReaderS :: MSF (ReaderT r m) a b -> MSF m (r, a) b
runReaderS = (forall c. (a -> ReaderT r m (b, c)) -> (r, a) -> m (b, c))
-> MSF (ReaderT r m) a b -> MSF m (r, a) b
forall (m2 :: * -> *) a1 (m1 :: * -> *) b1 a2 b2.
Monad m2 =>
(forall c. (a1 -> m1 (b1, c)) -> a2 -> m2 (b2, c))
-> MSF m1 a1 b1 -> MSF m2 a2 b2
morphGS ((forall c. (a -> ReaderT r m (b, c)) -> (r, a) -> m (b, c))
 -> MSF (ReaderT r m) a b -> MSF m (r, a) b)
-> (forall c. (a -> ReaderT r m (b, c)) -> (r, a) -> m (b, c))
-> MSF (ReaderT r m) a b
-> MSF m (r, a) b
forall a b. (a -> b) -> a -> b
$ \a -> ReaderT r m (b, c)
f (r, a) -> ReaderT r m (b, c) -> r -> m (b, c)
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT (a -> ReaderT r m (b, c)
f a
a) r
r

-- | Build an 'MSF' /function/ that takes a fixed environment as additional
-- input, from an MSF in the 'Reader' monad.
runReaderS_ :: Monad m => MSF (ReaderT s m) a b -> s -> MSF m a b
runReaderS_ :: MSF (ReaderT s m) a b -> s -> MSF m a b
runReaderS_ MSF (ReaderT s m) a b
msf s
s = (a -> (s, a)) -> MSF m a (s, a)
forall (a :: * -> * -> *) b c. Arrow a => (b -> c) -> a b c
arr (\a
a -> (s
s, a
a)) MSF m a (s, a) -> MSF m (s, a) b -> MSF m a b
forall k (cat :: k -> k -> *) (a :: k) (b :: k) (c :: k).
Category cat =>
cat a b -> cat b c -> cat a c
>>> MSF (ReaderT s m) a b -> MSF m (s, a) b
forall (m :: * -> *) r a b.
Monad m =>
MSF (ReaderT r m) a b -> MSF m (r, a) b
runReaderS MSF (ReaderT s m) a b
msf