In many cases, it isn't clear to me what is to be gained by combining two monads with a transformer rather than using two separate monads. Obviously, using two separate monads is a hassle and can involve do notation inside do notation, but are there cases where it just isn't expressive enough?
One case seems to be StateT on List: combining monads doesn't get you the right type, and if you do obtain the right type via a stack of monads like Bar (where Bar a = (Reader r (List (Writer w (Identity a))), it doesn't do the right thing.
But I'd like a more general and technical understanding of exactly what monad transformers are bringing to the table, when they are and aren't necessary, and why.
To make this question a little more focused:
- What is an actual example of a monad with no corresponding transformer (this would help illustrate what transformers can do that just stacking monads can't).
- Are StateT and ContT the only transformers that give a type not equivalent to the composition of them with m, for an underlying monad m (regardless of which order they're composed.)
(I'm not interested in particular implementation details as regards different choices of libraries, but rather the general (and probably Haskell independent) question of what monad transformers/morphisms are adding as an alternative to combining effects by stacking a bunch of monadic type constructors.)
(To give a little context, I'm a linguist who's doing a project to enrich Montague grammar - simply typed lambda calculus for composing word meanings into sentences - with a monad transformer stack. It would be really helpful to understand whether transformers are actually doing anything useful for me.)
Thanks,
Reuben
Writer w (IO a)
is a value in theWriter
monad returning anIO a
- and that's different fromWriterT w IO a
- which is a value in theWriterT w IO
monad returning ana
. – Deservingt
for whicht m
is aMonad
for anyMonad
m. However, it is not true, in general, that the composition of two monads is a monad - because of this, there aren't many abstract operations (if any at all) that can be defined in terms of the composition of two monads (and without abstraction, programming in Haskell with monads would be very tedious). It is simply a coincidence that most of the transformers commonly encountered compositions of monads (i.e.WriterT x m
isCompose m (x,)
). – Lengellift
. – Countervail