[ghc-steering-committee] RecordDotSyntax: please express a view

Eric Seidel eric at seidel.io
Wed Dec 11 03:27:57 UTC 2019


On Tue, Dec 10, 2019, at 09:27, Simon Peyton Jones via ghc-steering-committee wrote:
> You may be arguing that naked `.x` is a *postfix operator*, rather like 
> factorial when we write 5!.  

I brought this up at some point during the discussion. Treating a bare `.x` as a postfix operator feels very natural to me, and then `(.x)` would be a natural way to refer to the operator itself.

I'm not at all sure what the precedence of such an operator should be, however. When I see an example like

> 	f a .b c .d e

I want to parse it (if at all) as

> 	f (a .b) (c .d) e

rather than

> 	((f a).b c).d e

However, when confronted with

>   xs  .map double
>       .filter isEven
>       .map square

I instinctively want to flip the precedences and parse it as

>   (((xs.map) double).filter isEven).map square

What a difference some newlines (or is it the real names?) makes! 

Perhaps some more examples will be instructive. Another example that came up was deeply nested field accesses that don't fit onto a single line.

>  x.foo
>   .bar
>   .baz

This will be parsed as

> ((x.foo).bar).baz

regardless of precedence, as there is no function application. What if we add one?

>  f x.foo
>     .bar
>     .baz

If function application binds more tightly than field selection, this would parse as

> ((f x.foo).bar).baz

If you instead wanted

> f (x.foo.bar.baz)

you could add parens

>  f (x.foo
>      .bar
>      .baz)

which still looks reasonable to me.

So I think I would be happy with bare `.lbl` being a postfix operator that binds less tightly than function application.


More information about the ghc-steering-committee mailing list