[Haskell-cafe] Haskell's prefix exprs

Stefan O'Rear stefanor at cox.net
Mon Jul 9 12:23:03 EDT 2007


On Mon, Jul 09, 2007 at 03:55:52PM +0200, Christian Maeder wrote:
> Hi,
>
> I would like haskell to accept the following (currently illegal)
> expressions as syntactically valid prefix applications:
>
> f = id \ _ -> []
> g = id let x = [] in x
> h = id case [] of [] -> []
> i = id do []
> j = id if True then [] else []
>
> The rational is that expressions starting with a keyword should extend
> as far as possible (to the right and over several lines within their
> layout).
>
> In this case the above right hand sides (rhs) are unique juxtapositions
> of two expressions. (This extension should of course apply to more than
> two expressions, i. e. "f a do []")
>
> Furthermore the above rhs are all valid if written as infix expressions:
>
> f = id $ \ _ -> []
> g = id $ let x = [] in x
> h = id $ case [] of [] -> []
> i = id $ do []
> j = id $ if True then [] else []

False.

f = runST $ do return ()

is a type error.

f = runST (do return ())

is legal.

So your proposal isn't as pointless as you think :)

> (In fact, maybe for haskell-prime "$" could be changed to a keyword.)
>
> Does this pose any problems that I haven't considered?

Not that I know of.  Indeed, the status quo is a (minor) pain to parse,
and in my Haskell compiler project I *wanted* to implement your
proposal.

> I think only more (and shorter) illegal haskell programs will become legal.
>
> Cheers Christian
>
> Maybe someone else can work out the details for Haskell's grammar

Not hard at all.  In http://haskell.org/onlinereport/syntax-iso.html,
change:

exp^10 ->  \ apat[1] ... apat[n] -> exp         (lambda abstraction, n>=1)
       |   let decls in exp                     (let expression)
       |   if exp then exp else exp             (conditional)
       |   case exp of { alts }                 (case expression)
       |   do { stmts }                         (do expression)
       |   fexp
fexp   ->  [fexp] aexp                          (function application)

aexp   ->  qvar                                       (variable)
       |   gcon                                       (general constructor)
       |   literal
       |   ( exp )                                    (parenthesized expression)
       |   ( exp[1] , ... , exp[k] )                  (tuple, k>=2)
       |   [ exp[1] , ... , exp[k] ]                  (list, k>=1)
       |   [ exp[1] [, exp[2]] .. [exp[3]] ]          (arithmetic sequence)
       |   [ exp | qual[1] , ... , qual[n] ]          (list comprehension, n>=1)
       |   ( exp^i+1 qop^(a,i) )                      (left section)
       |   ( lexp^i qop^(l,i) )                       (left section)
       |   ( qop^(a,i)[<->] exp^i+1 )                 (right section)
       |   ( qop^(r,i)[<->] rexp^i )                  (right section)
       |   qcon { fbind[1] , ... , fbind[n] }         (labeled construction, n>=0)
       |   aexp[<qcon>] { fbind[1] , ... , fbind[n] } (labeled update, n >= 1)

to:

exp^10 ->  [exp^10] aexp                        (function application)
aexp   ->  \ apat[1] ... apat[n] -> exp         (lambda abstraction, n>=1)
       |   let decls in exp                     (let expression)
       |   if exp then exp else exp             (conditional)
       |   case exp of { alts }                 (case expression)
       |   do { stmts }                         (do expression)
       |   qvar                                       (variable)
       |   gcon                                       (general constructor)
       |   literal
       |   ( exp )                                    (parenthesized expression)
       |   ( exp[1] , ... , exp[k] )                  (tuple, k>=2)
       |   [ exp[1] , ... , exp[k] ]                  (list, k>=1)
       |   [ exp[1] [, exp[2]] .. [exp[3]] ]          (arithmetic sequence)
       |   [ exp | qual[1] , ... , qual[n] ]          (list comprehension, n>=1)
       |   ( exp^i+1 qop^(a,i) )                      (left section)
       |   ( lexp^i qop^(l,i) )                       (left section)
       |   ( qop^(a,i)[<->] exp^i+1 )                 (right section)
       |   ( qop^(r,i)[<->] rexp^i )                  (right section)
       |   qcon { fbind[1] , ... , fbind[n] }         (labeled construction, n>=0)
       |   aexp[<qcon>] { fbind[1] , ... , fbind[n] } (labeled update, n >= 1)

All new ambiguities are resolved adequately by the let/lambda meta rule.

> (I've posted this message to glasgow-haskell-users before, but it
> applies to every Haskell implementation and should be discussed here.)

haskell-prime at haskell.org would be even better.

Stefan
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
Url : http://www.haskell.org/pipermail/haskell-prime/attachments/20070709/ba30c1b0/attachment.bin


More information about the Haskell-prime mailing list