module Foundation.Monad.Reader
(
MonadReader(..)
,
ReaderT
, runReaderT
) where
import Foundation.Internal.Base (($), (.), const)
import Foundation.Monad.Base
class Monad m => MonadReader m where
type ReaderContext m
ask :: m (ReaderContext m)
newtype ReaderT r m a = ReaderT { runReaderT :: r -> m a }
instance Functor m => Functor (ReaderT r m) where
fmap f m = ReaderT $ fmap f . runReaderT m
instance Applicative m => Applicative (ReaderT r m) where
pure a = ReaderT $ const (pure a)
fab <*> fa = ReaderT $ \r -> runReaderT fab r <*> runReaderT fa r
instance Monad m => Monad (ReaderT r m) where
return a = ReaderT $ const (return a)
ma >>= mab = ReaderT $ \r -> runReaderT ma r >>= \a -> runReaderT (mab a) r
instance MonadTrans (ReaderT r) where
lift f = ReaderT $ \_ -> f
instance MonadIO m => MonadIO (ReaderT r m) where
liftIO f = lift (liftIO f)
instance MonadFailure m => MonadFailure (ReaderT r m) where
type Failure (ReaderT r m) = Failure m
mFail e = ReaderT $ \_ -> mFail e
instance MonadThrow m => MonadThrow (ReaderT r m) where
throw e = ReaderT $ \_ -> throw e
instance MonadCatch m => MonadCatch (ReaderT r m) where
catch (ReaderT m) c = ReaderT $ \r -> m r `catch` (\e -> runReaderT (c e) r)
instance Monad m => MonadReader (ReaderT r m) where
type ReaderContext (ReaderT r m) = r
ask = ReaderT return