[Haskell-beginners] order of monad transformers

Stephen Tetley stephen.tetley at gmail.com
Wed Nov 4 04:49:02 EST 2009

> {-# LANGUAGE GeneralizedNewtypeDeriving #-}

Hello Mike

If the is a principal as such, I'd suggest that's working
out the return type that you want your run function to have.
Or more plainly - work out what you want the result to be.

Thats a bit gnomic of course, so here are two examples with
ErrorT (for failure) and WriterT (for logging), the ErrMsg type
is contrived slightly to be a distinct type.

This message should be literate Haskell if my mail
service likes me:

> module Transforming where

> import Control.Monad.Error
> import Control.Monad.Identity
> import Control.Monad.Writer

> type Log = String
> newtype ErrMsg = ErrMsg { getMsg :: String } deriving Show

> newtype EWI a = EWI {
>     getEWI :: ErrorT ErrMsg (WriterT Log Identity) a }
>   deriving (Functor, Monad, MonadWriter Log, MonadError ErrMsg)

The run functions are pretty /natural/ just the run functions
of the monad transformer stack in the reverse order.

Note the /outer tupling/ over the Either type in the run
function - runEWI always returns a log regardless of whether
the computation fails with an error...

[ without embellishments: (Either _ _,_) ]

> runEWI :: EWI a -> (Either ErrMsg a, Log)
> runEWI ma = runIdentity (runWriterT (runErrorT (getEWI ma)))

> newtype WEI a = WEI {
>     getWEI :: WriterT Log (ErrorT ErrMsg Identity) a }
>   deriving (Functor, Monad, MonadWriter Log, MonadError ErrMsg)

Note the Either type has an inner tuple in the run function -
runWEI returns a log /only/ when the computation succeeds otherwise
it fails with just an error...

[ without embellishments: Either _ (_,_) ]

> runWEI :: WEI a -> Either ErrMsg (a, Log)
> runWEI ma = runIdentity (runErrorT (runWriterT (getWEI ma)))

Support code

> instance Error ErrMsg where
>   noMsg = ErrMsg ""
>   strMsg = ErrMsg

More information about the Beginners mailing list