Advertisement
Revolucent

Simple Environment Monad

Nov 24th, 2020 (edited)
1,540
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. {-# LANGUAGE FlexibleInstances #-}
  2. {-# LANGUAGE MultiParamTypeClasses #-}
  3.  
  4. module Lib where
  5.  
  6. {-
  7. This is a simple environment Monad transformer called simply E. It has no
  8. use whatsoever except to show the basics of how to construct such a thing.
  9.  
  10. It turns out that it's easier in most cases to write a monad transformer
  11. than it is to write a monad, because the "heavy lifting" can in most cases
  12. be forwarded to the transformed monad. (At the cost of some efficiency,
  13. though newtype helps a lot with this.)
  14.  
  15. Don't use this. Use ReaderT instead.
  16. -}
  17.  
  18. import Control.Monad.IO.Class (MonadIO(..))
  19. import Control.Monad.Reader.Class (MonadReader(..))
  20. import Control.Monad.Trans (MonadTrans(..))
  21.  
  22. newtype E r m a = E { runE :: r -> m a }
  23.  
  24. instance Functor m => Functor (E r m) where
  25.   fmap f (E a) = E $ fmap f . a
  26.  
  27. instance Applicative m => Applicative (E r m) where
  28.   pure = E . const . pure
  29.   (E f) <*> (E a) = E $ \r -> f r <*> a r
  30.  
  31. instance Monad m => Monad (E r m) where
  32.   return = pure
  33.   (E a) >>= f = E $ \r -> a r >>= \b -> runE (f b) r
  34.  
  35. instance MonadTrans (E r) where
  36.   lift = E . const
  37.  
  38. instance MonadIO m => MonadIO (E r m) where
  39.   liftIO = lift . liftIO
  40.  
  41. instance Monad m => MonadReader r (E r m)  where
  42.   ask = E return
  43.   local t (E a) = E $ a . t
  44.  
  45.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement