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

_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to