[Haskell-cafe] Stacking monads
jonathanccast at fastmail.fm
Thu Oct 2 17:26:26 EDT 2008
On Thu, 2008-10-02 at 20:53 +0100, Andrew Coppin wrote:
> Jonathan Cast wrote:
> > On Thu, 2008-10-02 at 18:18 +0100, Andrew Coppin wrote:
> >> After an insane amount of time making my head hurt, I disocvered that
> >> the type "Either ErrorType (ResultSet State)" is actually a monad.
> > It's a monad if you can write a function
> > join :: Either ErrorType (ResultSet (Either ErrorType (ResultSet alpha)))
> > -> Either ErrorType (ResultSet alpha)
> > (which follows from being able to write a function
> > interleave :: Either ErrorType (ResultSet alpha)
> > -> ResultSet (Either ErrorType alpha)
> > satisfying certain laws). Otherwise not, as you noticed.
> Er... OK. Yes, I guess that kind of makes sense...
> >> Since ResultSet *just happens* to also be in Functor,
> > It doesn't just happen to be one. liftM is *always* a law-abiding
> > definition for fmap, when used at a law-abiding monad.
> I'm lost...
> (What does liftM have to do with fmap?)
OK, I'll try again. If I have a Haskell type constructor m, and m has a
law-abiding instance of Monad, then
instance Functor m where
fmap = liftM
is *always* a law-abiding instance of Functor.
Furthermore, if m is an instance of Functor, then according to the
fmap = liftM
is one of the monad laws.
> > (This is why
> > posters here are always bringing up head-hurting category theory, btw.
> > Absorbing it sufficiently actually teaches you useful things about
> > Haskell programming.)
> That would be a surprising and unexpected result.
It also happens to be true. Most computer-related technologies started
as engineering solutions, and pulled in mathematical concepts mostly
when those concepts managed to inspire vaguely similar engineering
solutions. Haskell doesn't have that kind of heritage; its ultimate
ancestor is ML, which was originally a component of a theorem-proving
system, and its design has traditionally been (despite denials) about
pulling concepts from math directly into programming.
> After all, knowing
> about set theory doesn't help you write SQL...
SQL has an extremely tenuous relationship to set theory. Set theory can
sometimes inspire SQL database design, and it can excuse features that
would otherwise just be weird, but mostly SQL queries return lists, not
> >> At this point I am sorely tempted to just change ResultSet to include
> >> the error functionallity I need. However, ResultSet is *already* an
> >> extremely complicated monad that took me weeks to get working
> >> correctly...
> > What does it look like?
> A list, basically. (But obviously slightly more complicated than that.)
Nuts. We know how to turn  into a real monad transformer, but it's
ugly. Nevertheless, if you could post the actual type definition, it
might make this easier to do.
> > Quite possibly it can be factored out into
> > smaller pieces using monad transformers. (In which case adding error
> > handling is just sticking in another transformer at the right layer in
> > the stack --- that is, the layer where adding error handling works :).
> Well I'm *already* trying to layer an error transformer on the top and
> it's failing horribly.
Right. The most global property of the system goes with the monad
transfomer on bottom.
> I don't see how splitting things up even more
> could do anything but make the program even *more* complex.
Your problem isn't complexity, it's that the monad transformer that goes on top isn't implemented as one (so it wants to go on bottom). Re-factoring might make it easier to generalize that problem away. Or not.
> >> Does anybody have any idea how this whole monad stacking craziness is
> >> *supposed* to work?
> > No. 
> Ah, good. :-)
> > But we know how it *can* work; this is what monad transformers exist to
> > do. You want to either change ResultSet to be a monad transformer,
> > or
> > you want the monad ErrorT ErrorType ResultSet. Very little can be said
> > in general without knowing what ResultSet looks like.
> I thought ErrorT was a class name...?
No. It's a (higher-order) type constructor.
More information about the Haskell-Cafe