-- | Extension of a monad with a read-only environment module Mini.Transformers.ReaderT ( -- * Type ReaderT, -- * Reading ask, -- * Runners runReaderT, ) where import Control.Applicative ( Alternative ( empty, (<|>) ), ) import Control.Monad ( ap, liftM, ) import Mini.Transformers.Class ( MonadTrans ( lift ), ) {- - Type -} -- | A monad with read-only type /r/, inner monad /m/, and return type /a/ newtype ReaderT r m a = ReaderT { runReaderT :: r -> m a -- ^ Unwrap a 'ReaderT' given a read-only value } instance (Monad m) => Functor (ReaderT r m) where fmap = liftM instance (Monad m) => Applicative (ReaderT r m) where pure = ReaderT . const . pure (<*>) = ap instance (Monad m, Alternative m) => Alternative (ReaderT r m) where empty = ReaderT . const $ empty m <|> n = ReaderT $ \r -> runReaderT m r <|> runReaderT n r instance (Monad m) => Monad (ReaderT r m) where m >>= k = ReaderT $ \r -> runReaderT m r >>= (`runReaderT` r) . k instance MonadTrans (ReaderT r) where lift = ReaderT . const {- - Reading -} {- | Fetch the read-only value > foo = do > r <- ask > bar r -} ask :: (Monad m) => ReaderT r m r ask = ReaderT pure