[Haskell-cafe] Proposal for adding finallyError to MonadError
David Sorokin
david.sorokin at gmail.com
Thu Aug 8 14:51:37 CEST 2013
Hi, Café!
I have a proposal. I offer to add a new function to the MonadError type
class:
finallyError :: MonadError e m => m a -> m b -> m a
This is a generalization of the standard finally function that has the
following signature:
finally: IO a -> IO b -> IO a
Like function finally, the finallyError function runs the first
computation and then runs the second computation regardless of whether
an error might arise in the first computation. The first computation
defines the result.
Introducing semantics of a possible cancellation of the m computation,
the finallyError function accepts an additional meaning. The second
computation must be performed even in case of cancelling the
computation, while function catchError must be ignored. It literally
means that the finallyError function cannot be expressed in terms of the
catchError function.
This idea is essentially inspired by the F# async workflow that does
allow cancelling the Async computation. I implemented a similar monad
Simulation.Aivika.Cont.Cont for my simulation library Aivika [1]. My
monad Cont is an extension of the standard monad with the same name. It
uses continuations (namely, three different continuations within one
computation). It supports the exception handling and it allows
cancelling the computation (the liftIO function should also call
finallyError to catch the possible cancellation event if my Cont was a
generic monad transformer).
In the simulation the cancellation of the computation (actually, of the
discontinuous process) is a typical use case. Therefore it should be
executed as fast as possible. If I raised a specialized IOException for
the cancellation event, then it would be a more costly operation. This
is a practical point why the finallyError function cannot be expressed
in terms of catchError.
Another reason is that the catchError function can eat the cancellation
exception, which would be absolutely unacceptable. This is a theoretical
reason for introducing finallyError.
The finallyError function is very useful for guaranteed releasing the
external resources (such as the modeled entities in Aivika) in case of
raising an exception and even in case of cancelling the active
computation, which is important for simulation, for example.
Regarding the standard instances of MonadError, the finallyError
function seems to be simple for implementing. It is difficult mainly for
the Cont-based monads. So, in Aivika it is more difficult than
catchError for my Cont monad.
The actual name of the function is not important but here it looks
consistent with other functions of the MonadError type class.
Finally, the finallyError function can be actually defined in an
additional type class, which would extend MonadError like that how the
ArrowChoice type class extends Arrow.
Kind regards,
David Sorokin
[1] https://github.com/dsorokin/aivika
More information about the Haskell-Cafe
mailing list