On Wed, Jan 21, 2015 at 4:36 AM, Simon Marlow <marlowsd@gmail.com> wrote:
On 20/01/2015 23:07, Edward Kmett wrote:

It is a long trek from "this is plausible" to "hey, let's bet the
future of records and bunch of syntax in the language on this".

Absolutely.  On the other hand, this is the first proposal I've seen
that really hits (for me) a point in the design space that has an
acceptable power to weight ratio.  Yes there are some corners cut, and
it remains to be seen whether, after we've decided which corners we want to uncut, the design retains the same P2W ratio.

A couple of answers to specific points:

Re #1

The main term and type level bits of syntax that could be coopted
that aren't already in use are @ and (~ at the term level) and things
like banana brackets (| ... |), while that already has some other,
unrelated, connotations for folks, something related like {| ... |}.
We use such bananas for our row types in Ermine to good effect.

The latter {| ... |} might serve as a solid syntax suggestion for the
 anonymous row type syntax.

Why not just use { ... } ?

Mostly because it would conflict with the existing record syntax when used as a member of a data type.

Using { ... } would break all existing code, while {| ... |} could peacefully co-exist.

    data Foo = Foo { bar :: Bar }

vs. 

    data Foo = Foo {| bar :: Bar |}

You could, I suppose manually distinguish them using ()'s

    data Foo = Foo ({bar :: Bar })

might be something folks could grow to accept.

Another reason that comes to mind is that it causes a further divergence between the way terms and types behave/look, complicated stuff like Richard Eisenberg's work on giving us something closer to real dependent types.

Re #2

That leaves the means for how to talk about a lens for a given field
 open. Under Adam's proposal that had evolved into making a really
complicated instance that we could extract a lens from. This had the
 benefit over the current state of the `record` package that we could
 support full type changing lenses. Losing type-changing assignment
would be a big step back from the previous proposal / the current
state of development for folks who just use makeClassy or custom lens
production rules with lens to get something similar, though.

But the thing we never found was a nice short syntax for talking
about the lens you get from a given field (or possibly chain of
fields); Gundry's solution was 90% library and almost no syntax. On
the other hand Adam was shackled by having to let the accessor be
used as a normal function as well as a lens. Nikita's records don't
have that problem.

Having no syntax at all for extracting the lens from a field
accessor, but rather to having it just be the lens, could directly
address that concern. This raises some questions about scope, where
do these names live? What happens when you have a module A that
defines a record with a field, and a module B that does the same for
a different record, and a module C that imports both, but, really, we
had those before with Adam's proposal, so there is nothing new
there.

Right.  So either
(a) A field name is a bare identifier that is bound to the lens, or
(b) There is special syntax for the lens of a field name

If (a) there needs to be a declaration of the name in order that we can
talk about scoping.  That makes (b) a lot more attractive; and if you
really find the syntax awkward then you can always bind a local variable
to the lens, or export the names from your library.

Alternately (c) we could play games with ensuring the "name" is shared despite coming from different fields.

As a half-baked idea, if we pretended all field accessors were names from some magic internal GHC.Record.Fields module, so that using 

data Foo = Foo {| bar :: Bar, baz :: Baz |} 

would add an `import GHC.Record.Fields (bar, baz)` to the module. These would all expand to the same Symbol-based representation, behind the scenes, so that if two record types were used that used the same names, they'd just work together, with no scoping issues.

This has the benefit that users could write such import statements by hand to use fields themselves, no sigils get used up, and the resulting code is the cleanest it can be.

-Edward