I've been looking at the syntax of LHSes with Brian Boutel.
These are essentially the same for both Haskell 1.1 and 1.2.

As stated in the reports, the syntax is very irregular, allowing
parentheses in some circumstances, but not in others.  The result seems
quite arbitrary.

        f = ...                 -- LEGAL
        (f) = ...               -- LEGAL
        f x = ...               -- LEGAL
        (f x) = ...             -- ILLEGAL
        (f) x = ...             -- ILLEGAL
        f x y = ...             -- LEGAL
        (f x) y = ...           -- LEGAL
        (f x y) = ...           -- ILLEGAL
        x `f` y = ...           -- LEGAL
        (x `f` y) = ...         -- ILLEGAL
        (x `f` y) z = ...       -- LEGAL
        x `f` y z = ...         -- ILLEGAL

n+k patterns add an additional level of complication.

        (x + 1) * y = ...       -- Definition of *
        (x + 1) y = ...         -- Definition of +
        (x + 1) = ...           -- Definition of x
        ((x+1)) y = ...         -- Definition of +

It is impossible to decide whether an n+k pattern is being defined
until the symbol after the outermost parenthesis is read.  In an LR(1)
parser, such as those generated by Yacc, this causes an unresolvable
Reduce/Reduce conflict.

The reason this hasn't been mentioned before seems to be that
nobody's actually implemented this syntax (at least that's true
for hbc/Gofer, and Brian thinks it's true for Yale).  What
implementors tend to do is to implement:

        lhs ::=         pat "=" exp
        pat ::=         exp             { PRAGMA: valid pattern }

Of course, the legal pattern check will tend to give different results
in different compilers (some will be more flexible than others over
parentheses or (n+k) patterns).  I regard this as a jolly bad thing(*),
since it reduces portability.  It is also ugly (ad-hoc checks for valid
syntax are always less reliable than context-free grammars).

There are two solutions that I can see:

1)      Change the syntax of lhs patterns to explicitly 
        cover all parenthesised forms.  State which of these are
        n+k patterns (probably meta-syntactic).  This
        involves a similar ad-hoc check to that used
        by hbc/Gofer, but provides guidelines for a
        correct implementation.

2)      Change the syntax of lhs patterns to something like:

        lhs ::=   pat{i+1} varop(n,i) pat{i+1}
                | lpat{i}  varop(l,i) pat{i+1}
                | pat{i+1} varop(r,i) pat{i}
                | pat
                | var apat*

        and give a disambiguating rule for "n+k=..." (which could otherwise
        be either an n+k pattern or a definition of (+)).

As far as I can tell, the second alternative covers most or all real
uses, but in a much simpler syntax than the present one.

Kevin

PS      The reason I'm raising this now is that I overlooked the change
        in the 1.1 report (I assumed the syntax had stayed essentially
        the same, modulo the changes mentioned...).

(*)     (c), Simon PJ, 1991

Reply via email to