packages feed

mini-0.1.0.0: Mini/Transformers/ReaderT.hs

-- | 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