The usual pattern is to define a new type for your complete transformer package.
data A = A data E = E newtype MyBranchT ma = MyBranchT { getMyBranchT :: ExceptT E (StateT A m) a }
If there are any parts of the stack that themselves add meaningful new features, you also define new types for these parts.
Then you use GeneralizedNewtypeDeriving to get instances for all the different monad classes.
{-# LANGUAGE GeneralizedNewtypeDeriving #-} -- base import Control.Applicative import Control.Monad -- transformers import Control.Monad.IO.Class import Control.Monad.Trans.Class import Control.Monad.Trans.Except import Control.Monad.Trans.State.Lazy -- mtl classes import Control.Monad.Cont.Class import Control.Monad.Error.Class import Control.Monad.Reader.Class import Control.Monad.State.Class import Control.Monad.Writer.Class data A = A data E = E newtype MyBranchT ma = MyBranchT { getMyBranchT :: ExceptT E (StateT A m) a } deriving (Functor, Applicative, Monad, MonadIO, -- classes from base and transformers {- Alternative, MonadPlus, -} -- if E is a monoid MonadState A, MonadError E, -- classes from mtl that MyBranchT provides MonadCont, MonadReader r, MonadWriter w) -- classes from mtl that might be available from m
You will need to write a MonadTrans instance manually. lift always just lift once for each of the transformers in the stack.
instance MonadTrans MyBranchT where lift = MyBranchT . lift . lift
If there are any parts of the stack that themselves add significant new features to X , you also define a new MonadX class for these features, write MonadX instances for each of the monad transforms ( StateT , ExceptT , ContT , etc.) and get a MonadX instance for your transformer stack ( MyBranchT ).
You also usually use a synonym like MyBranchT Identity and function in runMyBranchT and runMyBranch
import Data.Functor.Identity type MyBranch a = MyBranchT Identity a runMyBranchT :: MyBranchT ma -> A -> m (Either E a, A) runMyBranchT mb s = runStateT (runExceptT (getMyBranchT mb)) s runMyBranch :: MyBranch a -> A -> (Either E a, A) runMyBranch mb s = runIdentity $ runMyBranchT mb s
Cirdec
source share