
This sounds very tedious! The right thing to do if you don't handle them, is of course to propagate exceptions up; however, then you need to update a 'throws' clause as you modify your implementation.
Sounds like a job for...Type Inference! Wouldn't it be nice if GHCi and Hugs' ":i foo" would tell you about the exceptions it could throw?
Do you just want exceptions to be displayed by an interpreter or do you want them used in the compiler (i.e., part of the Haskell language). I think it is straightforward enough to annotate expressions with the exceptions they can raise. As a first attempt, I'll use e :: ty^ex to indicate that an expression e has type ty and can raise exceptions ex. 1/0 :: Int^DivZero [1/i | i <- [0..]] :: [Int^DivZero] head [1/i | i <- [0..]] :: Int^{DivZero,Head_Empty} There's a few problems with simply adding this to Hugs/GHC as they stand though: 1) The exception parts of the types I showed should be types but, at present they are values. 2) Since exceptions accumulate towards the root, it's common to have a way of summarising a set of exceptions. Usually, this is done using some notion of inheritance so that numeric overflow, division by zero, etc might be summarized as 'ArithmeticError'. (Often the inheritance graph is a tree but I suspect it would be useful to have a DAG and to be able to define your own DAG just as you can define your own inheritance using type classes.) 3) This doesn't take the non-deterministic part of Haskell exceptions into account. Implementing the rules in the paper would be a good way of checking that the rules capture all the transformations that compilers like GHC do. Of course, to do this, you really need to push the exception-types all the way through the optimizer since it is the optimizer that introduces non-determinism. -- Alastair Reid