
Incidentally, the Haskell standard libraries (although not the report) also implement exitWith in terms of an exception. Personally, I think this is a great idea, as I'd rather not deal with two separate mechanisms for cleaning up in unexpected cases (i.e. bugs or exceptions or being passed a function that calls exitWith).
As I said, in case of a bug, it is not possible to reliably clean up. That an error is encountered proves that your assumptions about your program were wrong, and so the assumptions about allocated resources are probably wrong, too. To pick up Chris Smith's perspectives, cleaning up would be the task for the next higher level, for which your error is only an exception - it has hopefully kept track of the resources you allocated.
How would the boundary where an error becomes an exception be defined? Would you have some catch error and rethrow as exception type function which defines the next higher level? In my experience, the "level boundaries" depend a lot on the individual program, and are fuzzy because there are big boundaries and small boundaries. Which ones you think of depend on how disciplined you're being and what level the code is at. Say I have (withFile something_broken). I guess there's some kind of cosmic-ray chance that the broken code could somehow close the file itself and then withFile is in trouble (let's say close a file twice has some dire consequence), but the chance is low enough that there are bigger bugs to chase. Does that mean withFile defines a level boundary that can reliably clean up its broken callee? It seems to me that there are lots of bugs that you can reliably clean up after.
It seems that nobody except me is interested in handling specifically (up to a certain level) the exceptional cases that an IO action can lead to. If I see the type signature getLine :: IO String I have no idea, what kind of exceptions can occur. I even have to be prepared to get OpenGL exceptions. Even error codes in C are more informative in this respect. I would have to handle some exceptions which look reasonable to me, and use a catch-all or rethrow-all mechanism for the rest. Possibly the proposers of the extensible exception method like to rely entirely on catch-all or rethrow-all just like errors. Wouldn't getLine :: ErrorT IOError IO String be much clearer?
It think it would be interesting, though not really solving some big problem I've been having, though sometimes problems are obvious only in retrospect. Is there an implementation to experiment with? But... isn't it out of the scope of this proposal? And I'm not sure how it fits in with the errors vs. exception distinction, or even what the api for errors would look like. A parallel set of throwError catchError etc.? Then it would just be a different kind of exception.