Simon and Alastair,

This sounds like what I wanted.  Just a few questions:
> * A value of Haskell type T can be
>       EITHER one of the values we know and love 
>              (bottom, or constructor, or function,
>               depending on T),
> 
>       OR it can be a set of exceptional values.

> * raise :: String -> a
>   (raise s) returns a single exceptional value, named by string s

I presume that the programmer does not need to declare that a function
may throw an exception ... that it is inferred from the "raise" in the
function.  Furthermore, I assume that you can use the return value in
another function without unwrapping it e.g.

divide x y = if y==0 then raise DivideByZeroException
divideCaller x y = 1.0 + (divide x y)

Could you give a code example to clarify if I am mistaken?
 
> * All strict operations (case, +, etc) return the union of
>   the exceptional values returned by their strict arguments
>   For example, if both arguments to "+" return an exceptional value
>   then "+" returns both. Similarly, any strict context.  

It would make debugging easier if the exception picked was consistent
accross implementations.  It doesn't matter which one, but it does matter
that it is the same.  (maybe you require that Exceptions implement Ord, 
or sort based on the Hashvalue of the constructor)

> * handle :: (String -> IO a) -> IO a -> IO a
>   (handle h a) tries to perform the action a.
>   If doing so delivers a set of exceptional values then
>   apply the exception handler h to the string that names
>   one of them.  It is not defined which of the exceptional 
>   values is picked.

As noted above, there should be some cannonical order.
But, again I am having a little trouble understanding what you are saying
here.  Can you give some example code?

Also, why do you have String here?  Why can't exceptions be typed like in
Java?  Maybe exceptions should be a class and you use existential types...
(I just read a paper on polytypic functions last night...maybe those?)

> The neat thing about this is that the exceptions can
> be *raised* in arbitrary purely functional code, without
> violating referential transparency.  The question of
> which exception is chosen is done in the IO monad, where
> of course it is allowed to be non-deterministic.

If you can do the above and you can stay consistent about which exceptions
you return then you should be able to catch exceptions in arbitrary purely
function code as well, right?
(yes, I know I am changing positions again, but I am still learning).  

> (It is likely that successive runs will actually give
> the same behaviour, but recompiling the program with
> (say) different optimisation levels might change the order
> of evaluation, and hence change which exception is tripped
> over first.)

Just to reiterate.  I strongly urge you to ensure consistent exception
behavior.  As a matter of course, two different compiles should not result
in two different programs.  When you distribute your program to users,
add features, and distribute again, you don't want to diagnose the same
problem in two different ways in two different versions.  It makes
customer service just that much harder.

> We're implementing an experimental version of this
> in GHC, integrated with the IO monad exceptions, so that

As a matter of course, should we assume that these extensions
(exceptions, existentials) will become part of Haskell or are they just
part GHC?  Will they be part of Hugs?
 
-Alex-
___________________________________________________________________
S. Alexander Jacobson                   i2x Media  
1-212-697-0184 voice                    1-212-697-1427 fax






Reply via email to