
On Aug 31, 2009, at 11:02 PM, Edward Z. Yang wrote:
Hello all,
I've been looking at [1] and trying to make tops and bottoms (pardon the pun) of error handling in Haskell. I am still uncertain of what to do.
The problem, I think, is that it really depends on the situation. One also should distinguish between errors and exceptions -- errors being when the program/programmer is faulty, and exceptions being signals of expected conditions. The choice is really about when you want to always continue, what the appropriate level to test for failure is, and what to do on various exceptional conditions. I tend to think that pure functions should always return pure results, and error calls should be reserved for labeling actual error situations (i.e. code paths that should never be taken). Then when you want to assert that the result will never occur, you can write a mayToError (i.e. a labeled fromJust) or eitherToError function. Either String should of course not be used to represent a range of string exceptions, but should be thought of as returning a single exception (i.e. "Unable to Parse") with accompanying explanatory text. If you need to make sure that a pure value in IO doesn't contain either an error or a bottom, I would suggest using evaluate and rnf judiciously, both of which are important to understand, not just for error handling, but also for performance. Cheers, S.
I recognize that there are different areas of code that may have different requirements for errors:
* Pure code that is simple enough can probably get away with returning Maybe a
* Pure code that has multiple failure modes (the canonical example is parsing) should return a Either e a. The type of e is a little difficult: many standard libraries seem to use String, but coming from Python this seems analogous to the long deprecated "string exceptions", which are quick and easy but not long-term maintainable due to lack of an easy way to match for them. This leads naturally into Either MyError, which is supported using throwError and catchError.
* However, [1] specifically warns against using this technique in the IO monad, and I need a way to short circuit execution when a crucial pure operation fails (in Python, this would have just been an uncaught exception). This suggests using ErrorT on IO, however, [1] also claims that this is generally not a good idea, and suggests to use throwDyn (which actually looks like it's been renamed to throw)
* Unfortunately, when I've tried to use this technique, I've run up against the fact that throw is implemented using bottom, so if I do a throw in a pure function, the exception might not actually surface up until I'm, say, attempting to print its return value to IO. Denizens on #haskell have instructed me to treat bottom as the bane of existence and opt for stacking ErrorT on IO (it would be nice to know if this was a good idea or bad idea)
At which point, I am most thoroughly confused. Pointers, please!
Cheers, Edward
[1] http://www.randomhacks.net/articles/2007/03/10/haskell-8-ways- to-report-errors _______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners