Opened 7 years ago

Last modified 3 years ago

#5972 new feature request

option to suppress (Monomorphic) record selector functions

Reported by: AntC Owned by:
Priority: normal Milestone:
Component: Compiler Version:
Keywords: records Cc: adamgundry, mpickering
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: None/Unknown Test Case:
Blocked By: Blocking:
Related Tickets: Differential Rev(s):
Wiki Page:

Description

This proposal is a modest step towards freeing up the record fieldname namespace, without in any way pre-judging how the 'narrow namespace issue' might get addressed.

There is to be a compiler flag (suggestion) -XNoMonoRecordFields. (Default value ‑XMonoRecordFields, to give H98 behaviour.)

-XNoMonoRecordFields suppresses creating the field selector function from the field name in a record-style data declaration.

Suppressing the function frees up the namespace, to be able to experiment with various record/field approaches -- including the 'cottage industry' of Template Haskell solutions.

In particular, this means we can declare more than one record type within a module using the same field name.

For background, details, use cases, see: http://hackage.haskell.org/trac/ghc/wiki/Records/DeclaredOverloadedRecordFields/NoMonoRecordFields

(Contrast ticket #3356 {-# LANGUAGE NoTraditionalRecordSyntax #-}, which suppresses far too much (IMHO).)

Change History (17)

comment:1 Changed 7 years ago by simonmar

difficulty: Unknown

Seems like a good idea - but why only monomorphic selector functions? It would make more sense to me to just not generate any selector functions. -XNoFieldSelectors?

comment:2 Changed 7 years ago by simonpj

I agree with Simon M. by all means submit a patch to that effect. (Don't forget the documentation.)

comment:3 in reply to:  1 Changed 7 years ago by AntC

Replying to simonmar:

why only monomorphic selector functions? ... -XNoFieldSelectors?

Thanks Simon, I am asking to suppress all H98-style field selectors, including those whose field's type is parametric polymorphic or higher-ranked. Perhaps describing what I want as 'Mono' is therefore misleading. I mean H98 selectors are mono in the sense of applying only to a single record type and yielding a single type from that field in that record (which could be polymorphic).

I'm looking forward to one day having overloadable field selectors which could apply to more than a single record type. (But I'm trying not to pre-judge the outcome from the 'Records in Haskell' debate.) This modest proposal is acknowledging we need to take a step back to facilitate some experimantation before we can go forward.

So I think calling the flag -XNoFieldSelectors might close off that future. Perhaps instead -XNoH98FieldSelectors? (I'm trying not to bikeshed on the lexical details.)

Simon PJ: I don't think we need a separate patch, I'm looking for the same as Simon M, I just need a better way to explain it, perhaps.

comment:4 Changed 7 years ago by igloo

Milestone: 7.8.1
Owner: set to igloo

comment:5 Changed 6 years ago by adamgundry

Cc: adam.gundry@… added
Owner: changed from igloo to adamgundry

I'm looking at this as part of my work on implementing overloaded record fields.

comment:6 Changed 5 years ago by thoughtpolice

Milestone: 7.8.37.10.1

Moving to 7.10.1.

comment:7 Changed 5 years ago by thoughtpolice

Milestone: 7.10.17.12.1

Moving to 7.12.1 milestone; if you feel this is an error and should be addressed sooner, please move it back to the 7.10.1 milestone.

comment:8 Changed 4 years ago by thoughtpolice

Milestone: 7.12.18.0.1

Milestone renamed

comment:9 Changed 4 years ago by adamgundry

Owner: adamgundry deleted

comment:10 Changed 4 years ago by adamgundry

Cc: adamgundry added; adam.gundry@… removed

comment:11 Changed 4 years ago by thomie

Milestone: 8.0.1

comment:12 Changed 3 years ago by mpickering

Cc: mpickering added

comment:13 Changed 3 years ago by mpickering

This sounds good in theory but there are some namespacing problems.

Say that we just want to suppress the record selectors, that is easy enough to achieve, but the intention is clearly that users can then define their own selectors with whatever semantics they want with the same names as the field labels. A field label and record selector are currently the same thing. In order to resolve record updates, the current implementation looks up the record selector with the right name. It would seem that a correct solution would place field labels in a separate namespace to variables so they would become truly distinct and properly distinguish the record selector and the field label.

comment:14 Changed 3 years ago by AntC

Hi Matthew, I guess this whole ticket has been overtaken by the DuplicateRecordFields extension in GHC 8.0. This ticket was written way before SPJ and Adam arrived at that approach. There might still be some lensaholics who hanker after the namespace. For the record ...

A field label and record selector are currently the same thing.

You might think that because they are spelt the same, and one always comes with the other under H98, but actually as at H98 they're not. And that's the point:

  • a record selector is a function, first-class. If the language didn't create one automatically, you could do it yourself.
  • a field label can only appear in specific record access contexts {inside curly braces}. It is not first-class; only syntax sugar for positional access to the fields of the constructor.

I agree there are namespace concerns if a user creates their own function with the same name (which is indeed the purpose). This chiefly affects module export/import. See the link in the OP for more detail.

It would seem that a correct solution would place field labels in a separate namespace ...

I believe the pre-DuplicateRecordFields implementation unsugarred the field labels so they didn't occupy a namespace atall. Perhaps the situation is now different with Overloaded labels.

comment:15 Changed 3 years ago by adamgundry

@AntC I think mpickering's point is that inside GHC, a(n unambiguous) field label is identified by the Name of its selector function when used inside curly braces. There's no real distinction between the two made by the implementation. Changing that would be possible, but tedious.

In the post-DuplicateRecordFields implementation, it is possible to distinguish between fields and non-fields during name resolution. Thus it probably wouldn't be too hard to implement a variant on this whereby enabling the extension suppressed all selector functions (local or imported) for expressions in the current module, just as DuplicateRecordFields changes the name resolution rules within a single module. The selectors would still be generated, they just wouldn't be in scope.

That wouldn't quite give the behaviour you describe on the wiki page with regard to import/export, because if you exported a field then client modules could use it as a selector (unless they enable the extension themselves). You would have the option to hide the field and export a lens of the same name though.

comment:16 in reply to:  14 Changed 3 years ago by mpickering

Replying to AntC:

Hi Matthew, I guess this whole ticket has been overtaken by the DuplicateRecordFields extension in GHC 8.0. This ticket was written way before SPJ and Adam arrived at that approach. There might still be some lensaholics who hanker after the namespace. For the record ...

A field label and record selector are currently the same thing.

You might think that because they are spelt the same, and one always comes with the other under H98, but actually as at H98 they're not. And that's the point:

  • a record selector is a function, first-class. If the language didn't create one automatically, you could do it yourself.
  • a field label can only appear in specific record access contexts {inside curly braces}. It is not first-class; only syntax sugar for positional access to the fields of the constructor.

I agree there are namespace concerns if a user creates their own function with the same name (which is indeed the purpose). This chiefly affects module export/import. See the link in the OP for more detail.

It would seem that a correct solution would place field labels in a separate namespace ...

I believe the pre-DuplicateRecordFields implementation unsugarred the field labels so they didn't occupy a namespace atall. Perhaps the situation is now different with Overloaded labels.

Hi Ant, yes, I am one of those 'lensaholics'. Adam is right that I was referring to the implementation where a field label is identified by the Name of the selector (in the non-overloaded case).

I don't think this is related to overloaded record fields really. When I read this ticket I didn't imagine that enabling this flag would allow duplicate field labels, just suppress the generation of the field accessors.

Anyway, this ticket was instructive because it showed how tightly intertwined the implementation is.

comment:17 Changed 3 years ago by AntC

Thank you Adam for the implementation detail.

Remember:

  • This ticket was raised 4+ years ago (strewth!) when there were huge debates raging about the "Records problem" and a great deal of nothing had been achieved. (It was even before PolyKinds and type-level Strings IIRC.) I wanted to free up some of the design space.
  • I am not an implementor, so what the ticket requests is in terms of an end-programmer's view.
  • My remarks just above (and back then) re field labels vs selectors are in terms of the language report [section 3.15]

"[Field] Selectors are top level bindings ... This [name] shadowing only affects selector functions; in record construction (Section 3.15.2) and update (Section 3.15.3), field labels cannot be confused with ordinary variables."

When I read this ticket I didn't imagine that enabling this flag would allow duplicate field labels, ...

No that wasn't the aim. I was merely aiming to avoid gobbling up the name space. DuplicateRecordFields is a different way to avoid it.

... just suppress the generation of the field accessors.

Anyway, this ticket was instructive because it showed how tightly intertwined the implementation is.

Yes. Isn't it! I rather wish I hadn't found that out. We still seem a long way from a decent records system.

Note: See TracTickets for help on using tickets.