[Haskell-cafe] Re: MonadCatchIO, finally and the error monad
aslatter at gmail.com
Sun Oct 17 14:46:00 EDT 2010
On Sun, Oct 17, 2010 at 1:04 PM, Arie Peterson <ariep at xs4all.nl> wrote:
> On Thu, 14 Oct 2010 12:01:59 +0200, Michael Snoyman
> <michael at snoyman.com> wrote:
>> [...] which I believe is a flawed
>> design in the MonadCatchIO-transformers package. Here are my thoughts
>> on this and what I think needs to be done to fix it.
>> Try running the code with each version of go uncommented. In the first
>> two, "sequel called" gets printed. However, in the third, it does not.
>> The reason is short-circuiting: if we remember from the definition of
>> finally, there are two cases we account for. If an exception is
>> called, catch addresses it. If not, we assume that the next line will
>> be called. However, in the presence of short-circuiting monads like
>> ErrorT, that line of code will never get called!
> Yes. That is the behaviour I would expect.
> There are two kinds of exceptional values in, for instance, 'ErrorT e
> IO a':
> • IO exceptions, in the "underlying monad" 'IO';
> • error values of type 'e', in the monad transformer 'ErrorT e'.
> The MonadCatchIO instance for ErrorT deals with the first kind only.
> Catching IO exceptions, and cleaning up after them, is what MonadCatchIO
> was invented for. I feel that I should not decide for all users how
> these two layers of exceptions should interact; keeping the MonadCatchIO
> instance oblivious to the underlying monad as much as possible seems
> like the safest/most general thing to do.
> Meanwhile, I can see why you would want 'finally' to also catch the
> ErrorT errors, in your example, and circumvent the short-circuiting.
> However, I'm not convinced that this is always the right (expected, most
> useful, ...) behaviour. Maybe I just need more convincing :-).
I think the big thing I would look for is that the second argument to
'finally' always run (barring calls to System.Exit or the universe
ending or whatever). Otherwise I wouldn't expect any other interaction
with the 'Left' half of ErrorT.
For example I wouldn't expect the 'error' half of 'try' to be run on
Left, but I would expect the cleanup tasks in 'bracket' to be
executed. Otherwise the function just isn't useful.
More information about the Haskell-Cafe