module Control.Monad.Trans.Reader.Extras where import Control.Monad.Trans.Reader import Control.Monad.Morph import Data.Functor.Identity -- | This function combines two different monadic effects, -- where one of the effects is a reader effect and the other is a -- producing effect. -- -- This version results in the reader monad's inner effect to be wrapped -- around the producing effect. -- This requires the Reader inner effect to be an MFunctor on Identity. -- -- This can enable past-Dependence. -- Elm has foldp : (a -> state -> state) -> state -> Signal a -> Signal state -- This is equivalent to a creating a @StateT state (Signal m) ()@ -- -- 'runReaderM' is a more general form of @StateT state (Signal m) ()@ where -- given a reader monad to transform "a" to "c" with effects, and an "as" -- monad that produces "a"s with other effects, run the result of "as" through -- the reader monad to produce "c"s with both effects. -- @ -- runReaderM :: Monad m => Reader a (State s) c -> m a -> StateT s m c -- runReaderM :: Reader a (State s) c -> Signal STM a -> StateT state (Signal STM) c -- runReaderM :: Reader a (State s) c -> Pipes.Concurrent.Input a -> StateT state Pipes.Concurrent.Input c -- @ runReaderM :: (Monad m, Monad (t m), MonadTrans t, MFunctor t) => ReaderT a (t Identity) c -> m a -> t m c runReaderM c as = do a <- lift as hoist generalize $ runReaderT c a -- | An alternate form of runReaderM where the producing effect is -- wrapped around the reader monad's inner effect. -- This requires the producing effect to be an MFunctor on Identity. runReaderM' :: (Monad m, Monad (t m), MonadTrans t, MFunctor t) => ReaderT a m c -> (t Identity) a -> t m c runReaderM' c as = do a <- hoist generalize as lift $ runReaderT c a