Hi everyone, I've been using Haskell for 1-2 months now, and feel fairly comfortable with the language. However, my #1 gripe is the difficulty of working with exceptions. I have two main complaints: difficulty of defining custom exceptions, and difficulty of handling exceptions. I've been working on a library of various bits of Haskell code. There are several things that could raise exceptions within that library. There's no real easy way to do it, and make it easy for people using the library to trap only my exceptions. I could just use error("foo: bar") and tell them to look for a string that starts with "foo:". It works, but it's clumsy, and unreliable too ("foo:" is a valid filename, for instance, and could be used in other exceptions.) My other choice is to use Dynamic for my exceptions, but that makes it even more difficulty to catch and handle, and requires the programmer to be ready to deal with a fairly esoteric part of Haskell. In OCaml, there is an exception keyword, that is essentially the same as a data keyword. It defines a new exception, and can use the same constructors, etc. that any other type can. It's very useful. In Python, the situation is even better. There, an object can be thrown as an exception. Moreover, when catching exceptions, you can match an exception by a particular object *or any of its parents*. That means that I can easily extend someone else's work, adding my own exceptions as child objects of the existing ones. When I want to catch exceptions, I can be as specific or as general as I want, and any code designed to catch the more general exceptions will keep working. Java also works this way. Now, on to catching errors. OCaml makes this easy: try (whatever) with End_of_file -> foo | My_custom_error x -> bar x Here, "whatever", "foo", and "bar x" must all be of the same type. If there is no error, whatever is returned. If there is an error that we catch, the given value is returned. Otherwise, the exception is passed on up. Python can work that way, but also adds another feature: try: blah moreblah finally: foo The code "foo" will be executed whenever an exception occurs in the try block, or whenever the block ends normally. In other words, it is *always* executed. This is useful for doing cleanup actions like closing network connections. Haskell's exception catching doesn't really have less functionality than OCaml (some might argue it has more), but it takes a lot more effort to compose, needing to provide a function that returns a function in many cases. The other annoying thing is forcing it to run in the IO monad. I don't really understand this restriction. If we're not dealing with IO code to start with, we have deterministic behavior (if something raises an exception on a given value once, it will do that every time). So why do we have: catchJust :: (Exception -> Maybe b) -> IO a -> (b -> IO a) -> IO a instead of: catchJust :: (Exception -> Maybe b) -> (c -> a) -> c -> (b -> a) -> a This would let us run an arbitrary function (so long as it takes one parameter) and handle the exception completely outside of the IO monad. I can't think of a theoretical reason that this wouldn't work, though I suppose I may be missing something. Thoughts? Flames? :-) -- John