Version française
Home     About     Download     Resources     Contact us    
Browse thread
'_a
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: -- (:)
From: skaller <skaller@u...>
Subject: Re: [Caml-list] Re: '_a
On Sat, 2005-01-29 at 01:46, Keith Wansbrough wrote:
> Stefan Monnier <monnier@iro.umontreal.ca> writes:
> 
> > > (b) the codomain is mis-specified, we actually have
> > > 	List.hd: 'a list -> Some 'a
> > 
> > Funny, I always assumed that the domain of List.hd was "'a list - []".
> 
> Yes, indeed.  Were List.hd of type 'a list -> 'a option, we'd be stuck
> if we ever wanted actually to _use_ the value: any function that
> attempted to extract it (say f : 'a option -> 'a) would have to have a
> similar type (f : 'a option -> 'a option).

Of course! That's what destructors are for.
Ultimately, there's no choice, no matter how you factor
it you cannot have a List.hd function returning a non sum:
destructors are the *only* way to analyse sums.

The data summation *must* be dualised by a destructor
to convert that data into control branches.

Note that List.hd actually does that .. but one
of the control paths is implicit (the one carried
by the exception).

> The only way out of this mess is to add a monad. 

That isn't the only way. I have a fairly large
project that only throw an exception in *one*
essential place (to get out of a really deep
complex recursion).

With one exception -- i do use 'monadic'
failwith () like functions to terminate 
when I detect an error (and I do use that a lot),
these are all caught at the top level (and they're
not allowed to be caught anywhere else).

Otherwise .. I find the 'pain' of using
destructors everywhere preferable to throwing
exceptions -- the additional complexity of
the control paths is a small price to pay
for their localisation. Meaning -- I sometimes
have trouble holding enough of a picture in my
head to understand my code, but with exceptions
I'm completely lost because half the code 
isn't even visible :)

>  OCaml already has
> one: return is implicit, bind is called ";", and the monad operations
> include "raise" and "try ... with ...".

Indeed, but that isn't necessarily a good monad
for all purposes (otherwise Haskell would be Ocaml
and wouldn't have any typeclasses .. LOL :)

In particular, raise is very nasty -- I can't say this
very well, but 'the monad is too global'. It's way too
powerful -- and thus too hard to reason about.

I think this is because it crosses abstraction boundaries.
You can't predict what a function will throw from its
interface, so you basically have lost control of your program.

As I understand it, Haskell style monads provide
better localisation (is that right?)

The problem with using destructors left, right, and centre,
is that you need heaps of extremely localised code to handle
all the cases. However going from that to total globality
is no solution. (In the first case the error handling
is too tighly coupled to the error detection, and in
the second too loosely coupled).

Exception specs try to relieve this but they don't work.
To me the solution appears to require some kind of
'static exceptions'.

Felix uses a non-local goto. This is definitely better
for some purpose than dynamic EH, since it ensures
every 'throw' has a matching 'catch'. The goto can be
wrapped in a closure and passed explicitly anywhere
inside the closures abstraction, allowing both
static and dynamic control path to be constructed:
either way the path is either manifest (by locality)
or explicit (by argument passing).

However this solution is not modular.
EG: you can provide a handler for division by zero,
by there's no guarrantee the client you pass it to
actually calls it for the correct error .. :)

Monads provide better modularity?

-- 
John Skaller, mailto:skaller@users.sf.net
voice: 061-2-9660-0850, 
snail: PO BOX 401 Glebe NSW 2037 Australia
Checkout the Felix programming language http://felix.sf.net