I am attempting to define an API to express a particular type of procedure in my program.
newtype Procedure a = { runProcedure :: ? }
There is
To complement the other answers, I'd like to describe how to figure this out in the general case. That is, given two transformers, what are the semantics of their two combinations?
I had a lot of trouble with this question when I was starting to use monad transformers in a parsing project last week. My approach was to create a table of transformed types that I consult whenever I'm unsure. Here's how I did it:
Step 1: create a table of the basic monad types and their corresponding transformers types:
transformer type base type (+ parameter order)
---------------------------------------------------------------
MaybeT m a m (Maybe a) b. Maybe b
StateT s m a s -> m (a, s) t b. t -> (b, t)
ListT m a m [a] b. [] b
ErrorT e m a m (Either e a) f b. Either f b
... etc. ...
Step 2: apply each monad transformer to each of the base monads, substituting in for the m
type parameter:
inner outer combined type
Maybe MaybeT Maybe (Maybe a)
Maybe StateT s -> Maybe (a, s) -- <== this !!
... etc. ...
State MaybeT t -> (Maybe a, t) -- <== and this !!
State StateT s -> t -> ((a, s), t)
... etc. ...
(This step is a bit painful, since there's a quadratic number of combinations ... but it was a good exercise for me, and I only had to do it once.) The key for me here is that I wrote the combined types unwrapped -- without all those annoying MaybeT, StateT etc. wrappers. It's a lot easier for me to look at and think about the types without the boilerplate.
To answer your original question, this chart shows that:
MaybeT + State :: t -> (Maybe a, t)
a stateful computation where there might not be a value, but there will always be a (possibly modified) state output
StateT + Maybe :: s -> Maybe (a, s)
a computation where both the state and the value may be absent