My inclination was (3) over (2), because it seems more elegant:
* it explains the interpretation of "f r.x", as you said, and
* it means that "f r .x" is not different from "f r.x" (I prefer to avoid whitespace-sensitivity if we can)

But I'm somewhat persuaded by the "f.map double .filter isEven" example. So there are swings and roundabouts here, I don't see an obvious best choice between (2) and (3).

Cheers
Simon

On Tue, 7 Jan 2020 at 11:29, Simon Peyton Jones via ghc-steering-committee <ghc-steering-committee@haskell.org> wrote:

Friends

I’d like to move our record-syntax discussion forward.  Link to proposal discussion, and December GHC steering committee debates.

No-space arguments

I believe have agreed that

               f r.x

(with no spaces around the dot, and no parens around r.x) means

               f (r.x)

That is, treat it consistently with qualified names.  I asked everyone to express a view; Iavor, Eric, Arnaud, Joachim, and Richard all said it was at least acceptable; others expressed no view.  So let’s take that as a decision, at least for now.

Naked selectors

Next question: how should we treat a “naked selector”, namely .x where there is no space after the dot, but there is a space before.  I think there are three viable choices:

  1. It’s simply illegal.   This defers the choice;  perhaps later we will have more experience to go on.
  2. It’s a postfix operator, binding less tightly than function application, but more tightly than any infix operator.   So then (r .x) means r.x, and (r .x .y) means r.x.y.   But (f r .x) means (f r).x.

This choice naturally supports chaining (nice to have, but not essential).  We can write

f .map double

  .filter isEven

meaning (f.map double).filter isEven

  1. It’s a postfix operator, binding more tightly than function application, just as record update does.  So then (f r .x) means (f r.x), and (f r .x .y s .z) means (f r.x.y s.z).

This choice allows us to regard our decision about (f r.x) as what naturally happens if we parse it as three lexemes: f, r, and .x.  But it also breaks the “function application binds more tightly than anything else” rule, just as (f r {x=3}) sadly does already.

It does not permit chaining, at least not without stacked-up parens.

In all three cases we allow (.x), meaning (\r. r.x).   For (2) and (3) we can regard it as a “section”, like infix operators only simpler because there is no argument.

I think this is the last major question we have to answer.

What are your views?   Personally I lean towards (2), but I could certainly live with (1).  I’m a bit reluctant to adopt (3).

Simon

 

_______________________________________________
ghc-steering-committee mailing list
ghc-steering-committee@haskell.org
https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee