> I have just been  trying to  use a local definition in a list comprehen-
> sion, and  found, of course, that it could not be done.  Thus, when list
> comprehensions  are being  used  to  define  complex  structures,  whole
> expressions  often have to  be repeated, which is  primitive, to say the
> least.  (Either  that, or  fudge it by drawing the local variable from a
> singleton list.)
> 
> I'm fairly sure that local definitions were possible in Miranda(TM), and
> I see they are permitted in Gofer.  

Yes, David Turner added these based on a description I posted to the FP
mailing list 3-4 years ago.  Mark included them in Gofer later.  One
other advantage of using definitional comprehensions rather than
generators is that they allow a more efficient implementation than the
one given by Phil Wadler in Simon Peyton Jones' book.

> Mark Jones explains why they are not
> part of Haskell, on page 44 of the Gofer manual:
> 
>     Local definitions: A qualifier of the form  pat = expr  [...]
> 
>         [ e | pat = exp ]  =  [ let pat=exp in e ]
> 
>     [...] There was a  certain amount of controversy surrounding the
>     choice of an appropriate syntax and  semantics for the construct
>     and consequently,  this feature  is not  currently part  of  the
>     Haskell standard.

A simple form should be in the Glasgow parser, if you use the appropriate
flag (-nonstandard).  As far as I remember, there were two concrete suggestions 
in my paper:

        lhs = exp
        let valdef

(this was pre-Haskell 1.2, so let would have been a new keyword).  Neither
of these forms is ambiguous WRT the existing grammar (though both require 
large lookahead, of course).  As an alternative to "let", I suggested "def".

The lhs = expr form is contentious, because of the possibility of
confusing "=" with "==", and therefore introducing a definition rather
than an expression.  This problem does already arise in Haskell,
but in a milder form.  Compare:

        f = x == y
        f == x = y

The "let" form could also be abused by a bad programmer, though in the
context of a list comprehension, this is unlikely (I don't recall
ever seeing a local definition in a guard, but maybe someone has done
this?).  Restricting the syntax of guards to avoid a problem would seem 
like a poor solution, though, because of the possibility of automatic 
source generation.

Here are the alternatives for a silly example, the final form
is equivalent, so long as the expression is a singleton.

        [ f x | x = 2,     x==2 ]
        [ f x | let x = 2, x==2 ]
        [ f x | def x = 2, x==2 ]
        [ f x | x <- [2],  x==2 ]

There are two alternative semantics for definitional comprehensions:
depending on whether match failure is _|_ (as with normal defns.)
or [] (as with generators).

Apart from choosing the right syntactic form (a relatively minor issue),
there should be nothing controversial about such comprehensions.
They add expressive power at almost zero implementation cost (my
original implementation added one significant line to a 20000 line
compiler).  I don't know how the other Haskell 1.3ers feel about these?

Kevin


Reply via email to