{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} module Lib where {- This is a simple environment Monad transformer called simply E. It has no use whatsoever except to show the basics of how to construct such a thing. It turns out that it's easier in most cases to write a monad transformer than it is to write a monad, because the "heavy lifting" can in most cases be forwarded to the transformed monad. (At the cost of some efficiency, though newtype helps a lot with this.) Don't use this. Use ReaderT instead. -} import Control.Monad.IO.Class (MonadIO(..)) import Control.Monad.Reader.Class (MonadReader(..)) import Control.Monad.Trans (MonadTrans(..)) newtype E r m a = E { runE :: r -> m a } instance Functor m => Functor (E r m) where fmap f (E a) = E $ fmap f . a instance Applicative m => Applicative (E r m) where pure = E . const . pure (E f) <*> (E a) = E $ \r -> f r <*> a r instance Monad m => Monad (E r m) where return = pure (E a) >>= f = E $ \r -> a r >>= \b -> runE (f b) r instance MonadTrans (E r) where lift = E . const instance MonadIO m => MonadIO (E r m) where liftIO = lift . liftIO instance Monad m => MonadReader r (E r m) where ask = E return local t (E a) = E $ a . t