On 10-Jun-1998, S. Alexander Jacobson <[EMAIL PROTECTED]> wrote:
> 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 ...

Correct.

> that it is inferred from the "raise" in the function.

The idea is that *any* function may potentially throw an exception.

> Furthermore, I assume that you can use the return value in
> another function without unwrapping it e.g.

Also correct.

> > * 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)

I think this would be difficult to implement efficiently.

Another possibility would be to specify that the exception returned
is the first one that would occur if the program is evaluated in
according to some particular order of computation.  This would be
easy to implement efficiently.  But it would break commutativity
of `+' and similar operators.  It would make it difficult for
implementations to evaluate programs in any order other than that
specified.  This might make it signficantly more difficult for
implementations to do things like automatically parallelize programs.

For Mercury, for which similar issues arise, we went with a compromise:
implementations are allowed to evaluate things in any order,
but they must also provide a way for the user to request that things
be evaluated strictly left-to-right.  This allows the user to choose
which is more important to them: efficiency or ease of debugging.

> > 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?

If you used some canonical ordering on exceptions, then yes.
But as I said above, I think that would be difficult to implement
efficiently.

The approach using an `NDSet' monad that I outlined in another post
allows you to catch exceptions in arbitrary purely functional code,
and is much easier to implement efficienctly.

-- 
Fergus Henderson <[EMAIL PROTECTED]>  |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>  |  of excellence is a lethal habit"
PGP: finger [EMAIL PROTECTED]        |     -- the last words of T. S. Garp.


Reply via email to