#2309: containers: specialize functions that fail in a Monad to Maybe

Dan Doel dan.doel at gmail.com
Sun May 25 07:58:44 EDT 2008


On Sunday 25 May 2008, Yitzchak Gale wrote:
> I personally would be happy with either Maybe or MonadPlus.
>
> I hope we don't miss out on getting rid of fail by arguing
> about Maybe vs. MonadPlus.

I don't think we should get rid of fail. There's nothing wrong with it, per 
se. It just shouldn't be in Monad, it should be in MonadPlus (or MonadZero if 
things get split back up 1.4 style). fail is mzero that takes a string to 
explain what happened. In fact, if the functions were revised to be 
restricted to MonadPlus, I'd expect it'd be a change only in the declared 
type signature. They'd likely still call fail because it provides slightly 
more information to the monads that can actually use it (Either e, IO, ...).

Having both fail and mzero as failure options isn't a real problem, because 
they should do the same thing in monads that have both (at least, off the top 
of my head; I may be forgetting some). The problem is calling fail in monads 
that don't have an mzero, because they don't have a notion of failure.

> Maybe is not arbitrary. It is the "unit" instance of MonadPlus. It can be
> lifted trivially into any other instance.

I didn't mean to say that Maybe is arbitrary. I meant that specializing to 
Maybe makes it more inconvenient to use with other MonadPlus instances, and I 
don't see a benefit to counter that.

Yes, you can trivially inject Maybe into an arbitrary MonadPlus. You can do it 
for any Foldable, in fact:

    Data.Foldable.msum . fmap return

But having to write liftMaybe whenever you want that has the potential to be 
annoying. We currently have the same problem with IO functions, where you 
have to stick a liftIO on everything if you want to wrap IO in a monad 
transformer.

That's not to mention potential information loss compared to fail. For 
instance, readMaybe doesn't subsume readIO, because the latter can report the 
difference between no parse and ambiguous parses. Using Either String covers 
that, except it's not declared a Monad except in mtl, because fail is in the 
wrong place.

I just think it's frustrating that we have abstractions that do exactly what 
we want, and then don't use them. :)

-- Dan


More information about the Libraries mailing list