[Haskell-cafe] What is MonadPlus good for?

Remi Turk rturk at science.uva.nl
Sun Feb 13 14:06:36 EST 2005


On Sun, Feb 13, 2005 at 01:31:56PM -0500, David Roundy wrote:
> On Sun, Feb 13, 2005 at 04:57:46PM +0100, Remi Turk wrote:
> > According to http://www.haskell.org/hawiki/MonadPlus (see also
> > the recent thread about MonadPlus) a MonadPlus instance
> > should obey m >> mzero === mzero, which IO doesn't. IOW, the
> > MonadPlus instance for IO (defined in Control.Monad.Error)
> > probably shouldn't be there.
> 
> True.  In the IO monad there are side effects that don't get "erased" when
> a later action raises an exception as that law would suggest.  But any
> IO-like monad that I'm likely to implement will have the same discrepancy,
> and in any IO code that catches "enough" exceptions to be bug-free will be
> immune to this issue.
> 
> Basically, the issue is that
> 
>    do { writeFile "foo" "bar"; writeFile "bar" "foo" } `catch`
>    \_ -> putStr "Couldn't create file\m"
> 
> may reach the putStr with or without the file "foo" existing, and there's
> no way to know whether or not it was created.  But that just means the code
> was written sloppily--that is, if the existence of that foo file is
> important.
> 
> In my uses of MonadPlus, I'd have other schemes essentially immitating IO,
> so they'd duplicate this behavior (later errors don't undo earlier
> actions), and well-written functions would depend on that.

But what if `instance MonadPlus IO' disappears from the libraries
some day? (which it should, IMO)

> It might be interesting to write a "backtracking" IO-like monad which
> obeyed m >> mzero === mzero.  I imagine you could do it for something like
> an ACID database, if you define === as meaning "has the same final result
> on the database", which of course would only be useful if the database had
> sufficient locking that it couldn't have been read between the original m
> and the later mzero.

You might be interested in the recent STM monad then
(Control.Concurrent.STM in GHC-6.4): `T' for Transactional.
However, though it supports both MonadPlus and exceptions, it
doesn't use MonadPlus for exceptions: It's used for
blocking/retrying a thread/transaction.

I never used it, so I'm not sure whether it makes any sense, but
wouldn't MonadError be a better candidate class to base it upon?

Greetings,
Remi

-- 
Nobody can be exactly like me. Even I have trouble doing it.


More information about the Haskell-Cafe mailing list