Marcin 'Qrczak' Kowalczyk <qrczak@knm.org.pl> writes:
Parsec [uses some variant of the error monad] and similar things. It tries to generate reasonable messages of the form "expecting foo, found bar" or "unexpected bar" annotated with source position, making use of labels of higher level syntactic constructs inserted in the grammar as well as individual characters matched.
I think this illustrates an important point about different approaches to exception handling. Parsing is a great example of where error monads are useful: 1) You expect the errors to be the common case instead of the very unlikely case (so you're willing to expend quite a bit of effort to handle them well). Typecheckers also fit into this category. 2) You really care about what the error message looks like. 3) Your code is either all machine generated (e.g., by happy) or you use combinators (e.g., >>= and return) so it is easy to thread the error monad through and to be consistent about doing it. In these case, I think error monads are the best choice. The Hugs/GHC exception catching that Andy Moran described is aimed at situations where these don't apply. Cases include: 1) Your program has to manipulate some real world (and stateful) object and it is not considered acceptable to leave it in some confused state. Examples include leaving windows open when a GUI equipped program crashes, a control system (like the joystick in a plane or controls in a lift) that suddenly stops responding, leaving a database in an inconsistent state, etc. 2) You write a library (e.g., Fran, HGL, etc.) where (hopefully) carefully written library code (which can be as full of error checks as you want) has to invoke user code and, somehow, recover and, either keep going or shut down cleanly. 3) Someone gives you a great library but their code doesn't use the error monad (or whatever) because the code was developed for a less demanding execution environment. The library is large and rewriting it is daunting. 4) You think you've used the error monad consistently and avoided calling all those "unsafe" Prelude functions like "head", "tail", "minimum", and "div" but you've got no good way of checking and you want your code to be robust. 5) You really don't care much which exception you get - as long as you get one. I think the two approaches complement each other rather well (but, of course, I'm biased...). -- Alastair Reid reid@cs.utah.edu http://www.cs.utah.edu/~reid/