
[oops, sent by accident...] On 08 April 2006 10:18, John Meacham wrote:
On Sat, Apr 08, 2006 at 12:11:51AM -0400, David Menendez wrote:
newtype ArithException a = ArithException a
data DivideByZero
throw (ArithException DivideByZero)
your code:
data MultiplyByZero throw (ArithException MultiplyByZero)
How would you use this to write a handler that captures any ArithException?
You would use the Typeable1 class in Data.Typeable. not perfect, but exception hierarchies shouldn't be too deep so it is not so bad.
I mentioned this solution to John G. off-list; the problem is that you end up needing to parameterise all the classes of exceptions (we'd have IOException a, ArrayException a, AsyncException a, etc.), and that seems ugly. Given that we've already made the Exception type sideways extensible with a simple application of type classes and dynamic types, we can take the technique a bit further to create an extensible hierarchy of exceptions, which is what John's arguing for. To create a new subclass of exceptions: --------- class (Typeable x, Show x) => ArithException x newtype AnyArithException = AnyArithException Dynamic deriving Typeable instance Exception AnyArithException instance Show AnyArithException where show (AnyArithException x) = show x throwArith :: ArithException x => x -> a throwArith x = throw (AnyArithException (toDyn x)) matchArith :: ArithException x => AnyArithException -> Maybe x matchArith (AnyArithException x) = fromDynamic x --------- and populating the subclass is just as easy as populating the root: --------- data DivideByZero = DivideByZero deriving (Typeable, Show) data Overflow = Overflow deriving (Typeable, Show) instance ArithException DivideByZero instance ArithException Overflow --------- catching is easy too. To catch *any* ArithException: --------- x `catch` \(e :: AnyArithException) -> print e --------- To catch a particular ArithException: --------- x `catch` \e -> case () of _ | Just DivideByZero <- matchArith e -> print e | otherwise -> throw e --------- To catch a mixture of ArithException and other exceptions: --------- x `catchAny` \e -> case () of _ | Just (IOException x) <- matchException e -> print x | Just arith <- matchException e, Just DivideByZero <- matchArith arith -> print arith | otherwise -> throwAny e --------- I like this, it seems like a natural extension of what we've already proposed. The fact that you have to use 'throwArith' rather than plain 'throw' is slightly annoying, though. Cheers, Simon
participants (1)
-
Simon Marlow