
On 03-Aug-2004, Alastair Reid
Another approach is to use a function:
inContext :: String -> a -> a
(implemented using mapException) like this:
inContext "evaluating expression" (eval env e)
to transform an exception of the form:
error "Division by zero"
into
error "Division by zero while evaluating expression"
As written, that won't work properly; you will get misleading error messages, due to lazy evaluation. If a division by zero exception is thrown, it may have occurred when computing the expression e, rather than in the function eval itself. Furthermore, if eval returns a compound type, this code won't catch all division by zero errors that occur while computing eval, only those that occur while computing the top-most node. To make it work properly, you can do something like class hyperSeq a where hyperSeq :: a -> b -> b inContext :: (hyperSeq a, hyperSeq b) => String -> (a -> b) -> a -> b and then inContext can force full evaluation of the input and output, making sure to force full evaluation of the input _before_ invoking mapException: inContext msg fn input = hyperSeq input $ mapException (...) $ let output = fn input in hyperSeq output output Of course then you rather completely lose lazy evaluation. But who wants lazy evaluation, anyway? :) -- Fergus J. Henderson | "I have always known that the pursuit Galois Connections, Inc. | of excellence is a lethal habit" Phone: +1 503 626 6616 | -- the last words of T. S. Garp.