I am trying to take e.g. ExceptT a (StateT A M)
, for some concrete type A
and monad M
, and wrap them up into my new custom monads.
First I identified that StateT A M
appears often in other contexts and thus I decided it would be best to wrap that alone in a monad M1
and then wrap ExceptT a M1
into M2
.
The desired property is to make M1
and M2
instances of MonadState
and the class of M
(lets assume it is called MyMonadClass
). Also M2
should be an instance of MonadError
.
First I started by simple type synonyms:
type MyState = StateT A M
type MyBranch a = ExceptT a MyState
then I thought that I would first sketch the instance declarations (without implementing the instance) and thats where I first got stuck. instance MonadState A (MyState)
seemed to not be the right syntax. I thought I would have to create newtype MyState' a = StateT a M
and then type MyState = MyState A
(Lets not use language extensions where not necessary).
However once I started converting the synonyms into newtype
declarations I started to lose the connection to the StateT A M
and ExceptT ...
types.
newtype MyState' s a = MyState' { runMyState :: s -> (s, a) }
type MyState = MyState' A
newtype MyBranch e a = MyBranch { runMyBranch :: MyState (Either e a) }
Now the transformers that are already implemented disappeared and I think I am trying to do something that does not make much sense. So my question is: How would one correctly wrap this kind of behaviour into new compound monads that make accessible the layers underneath so that one avoids unnecessary lifting and keeps things clear and well-organized.