Writing a rwst monad transformer

July 5, 2016

Writing a Monad Transformer

Typical examples of monads are Reader, Writer, Maybe, Either, State. Today I want to recap my part of my understanding of monads through the RWST monad. Also make it a monad transformer for the exercise.


import Control.Monad.Trans hiding (RWST)
import Control.Monad.State.Class

This how you encode the rwst monad. It has to be a function that reads both a read only value r and some state s. The RWST provides the following functionality, read a configuration value, thread a mutable state value, and accumulate a monoidal value. Stating it in other words the RWST monad provides a computational context where one have state, have a read only configuration, acumulate a value.

newtype RWST r w s m a = RWST {runRWST :: r -> s -> m (a, s, w) }
instance (Monad m, Monoid w) => Monad (RWST r w s m) where
    return a = RWST $ \r s -> return (a,s,mempty) 
    m >>= k =
       RWST $ \r s -> do
          (x, st, w) <- (runRWST m) r s
          (x', st',w') <- (runRWST (k x)) r st
          return (x', st', w `mappend` w')


instance (Monad m, Monoid w) => Applicative (RWST r w s m) where
    pure a = RWST $ \r s -> return (a,s,mempty)
    (RWST mf) <*> (RWST v) = 
     RWST $ \r s -> do
         (f,st,w) <- mf r s
         (a, st',w') <- v r st
         return (f a, st', w `mappend` w')
      
instance (Functor m, Monoid w) => Functor (RWST r w s m) where
    fmap f (RWST v) = RWST $ \r s -> fmap (\(x,st,w) -> (f x,st,w)) (v r s) 

MonadTrans typeclass is used for defining how a monad transformer talks to its inner monad. Or how the inner monad gets lifted into the context a the wrapper monad.

instance (Monoid w) => MonadTrans (RWST r w s) where
    lift m = RWST $ \r s -> do
        a <- m
        return $ (a,s,mempty)


instance (Monoid w, MonadIO m) => MonadIO (RWST r w s m) where
    liftIO = lift . liftIO