[Haskell-cafe] Re: MonadCatchIO, finally and the error monad

Michael Snoyman michael at snoyman.com
Fri Oct 15 04:48:07 EDT 2010

On Fri, Oct 15, 2010 at 10:22 AM,  <oleg at okmij.org> wrote:
> Michael Snoyman wrote:
>> I would prefer if the test read as:
>> > test33 = fmap (== Left "throwError") $ test3c (throwError "throwError" ::
>>  ErrorT String IO String)
>> Which never in fact returns True. Or, more to the point, the test is
>> never even called, since the runtime exception prevents it.
> If you prefer the raised exception to be reflected back into the monad
> it came from, that can be arranged. I have updated
>        http://okmij.org/ftp/Haskell/CaughtMonadIO.lhs
> to use your test:
>> test331 = fmap (== Left (show "throwError")) $
>>           test3c (throwError "throwError" :: ErrorT String IO String)
> *CaughtMonadIO> test331
> sequel called
> True
> The `show' is the artifact of `reconciling' Error and Exception
> classes. The class Error doesn't seem very informative; one may wonder
> if it is needed given that we already have Exception. If in your real
> code, the argument of throwError is actually an Exception, the show
> hack can be eliminated, where it is mentioned in the
> instance CaughtMonadIO (ErrorT e m). I can do the adjustment if you
> post more details about the desired functionality.

By the way, I completely agree that the Error typeclass is not very
useful, and I wish it would just disappear. I wrote the neither
package[1]- the modified error monad I keep mentioning- in large part
to avoid the Error typeclass. The other reason was the oprhan Monad
Either instance.

To the point at hand: I'm aware that you can promote the Error monad's
error type into a runtime exception, catch it, and pull it back down.
My point is that you shouldn't have to: there are perfectly valid
definitions of finally for the error monad that don't require any of
this trickery. Additionally, sometimes the error type cannot
(reasonably) be promoted to an exception, eg ErrorT (a -> b) m. We'd
have to start mucking around with dummy Show instances/blind wrappers.

I just finished writing up a post describing the MonadInvertIO
approach[2], which I think is a more appropriate solution to the
problem. It doesn't involve any runtime exception trickery, and works
for a number of other use cases, including memory allocation. I would
appreciate any critiques of my ideas.


[1] http://hackage.haskell.org/cgi-bin/hackage-scripts/package/neither
[2] http://docs.yesodweb.com/blog/invertible-monads-exceptions-allocations/#monadinvertio
(links straight to the appropriate section, skips the long buildup)

More information about the Haskell-Cafe mailing list