[ghc-steering-committee] #512: NoFieldSelectors as datatype annotation, Recommendation: reject

Adam Gundry adam at well-typed.com
Wed Nov 30 19:28:59 UTC 2022


On 30/11/2022 16:22, Joachim Breitner wrote:
> Am Mittwoch, dem 30.11.2022 um 14:08 +0300 schrieb Vladislav Zavialov:
>> 4. The fourth reason is that an easy workaround is available. Just
>> move declarations into a separate module with "NoFieldSelectors". I
>> understand that it might be unsatisfactory and inconvenient, but it
>> works and I'm weighing it against the maintenance cost mentioned in
>> (1).
> 
> I wonder if there is another work-around: If the motivation is a module
> full of TH-generated data types, and only some of them should get a
> FieldSelector, couldn’t TH generate those fieldselectors that are
> needed simply as plain functions?

The motivating use case seems to be this:

  * End user code defines a datatype Foo (in a module that may or may 
not have FieldSelectors enabled).

  * They then (perhaps via TH) define a datatype SqlFoo using the same 
field names, for which NoFieldSelectors must apply.

I guess we could say that the end user must set NoFieldSelectors on the 
whole module and then write or have TH code generate selectors for Foo. 
But that feels rather awkward, as does being forced to use separate 
modules. I think it would be much nicer if the code could say "use 
NoFieldSelectors for this specific definition".

It seems to me that the motivation is relatively compelling at the level 
of entire datatype declarations. Being able to toggle NoFieldSelectors 
for individual constructors or fields seems less convincing.


> This makes me wonder: can the effect of NoFieldSelectors be really
> undone using a plain function definition, or is there something about
> field selectors that is special? Ah, probably the export/import  story…
> I assume we don’t (yet?) have a way of bundling them with the type
> constructor so that `import TyCon(..)` gets them as well?

Right, we could imagine explicit bundling of selector functions with 
datatype constructors much as we have for pattern synonyms. That might 
be nice independently, but seems like it would still be annoying for the 
motivating use case though: the end user code will suddenly need the 
export list to explicitly list all the fields in all the datatypes it is 
exporting.


> I also wonder: Where do we want to steer Haskell here! While not a
> strict rule, I believe we _do_ want to avoid, if possible, from
> creating many different dialects in the long run, and (usually)
> extensions should at least be plausible to become the default
> eventually. Is that true for NoFieldSelectors? Do we envision that to
> eventually become the default? If so, pragmas for turning it on
> selectively don’t seem to be that useful.
> 
> (Until two days ago I would have been hesitant to imagine Haskell
> without FieldSelectors on by default. Two days I go for the first time
> worked on a code base with OverloadedRecordDot, and it felt
> surprisingly smooth and elegant. Now I could imagine Haskell in the
> long run weaning away from (automatic) field selector functions, and
> reaching a future where one uses dot notation (and pattern matching, of
> course) to get data out of records.)

I think it is too early to judge this. It's not inconceivable that 
NoFieldSelectors will become preferred in the future, but I think the 
in-between period will be long enough that wanting to set it on specific 
datatypes makes sense.


> About wanting to use modifier syntax instead: I sympathize with Matt’s
> hesitancy.  Modifier syntax is not only unimplemented, it is also
> untested, and (to me at least) it is unclear it will live up to the
> generality it tries to apply to. (For example, we’ll see if using the
> syntax of types is always the ergonomic syntax for annotation, if some
> annotation really need bespoke syntax; if having types there, which at
> least need to be name-resolutioned, may prevent their use in
> annotations that affect name resolution; etc. – I digress) So if Matt’s
> proposal was more compelling on other grounds, I may have suggested to
> allow it in Pragma style.
> 
> But Vlad makes good arguments about the suggested changes not really
> pulling their weight, and thus I concur with his recommendation.

The modifiers situation is very unfortunate. I'm not convinced we should 
insist on holding future proposals to an unimplemented/untested design. 
Perhaps there is a reasonable approach that uses neither pragmas nor 
modifiers?

Suggesting half-baked ideas when responding to a proposal is a bit 
risky, but how about this as an alternative: what if we add a new 
top-level declaration that enables a language extension for a block of 
declarations. I'll use "language" as a keyword here, but obviously the 
exact syntax is up for debate. For example:

   language NoFieldSelectors where
     data SqlFoo = SqlFoo...

This could also be used to resolve existing violations of the 
ideological principle Vlad mentions (that pragmas shouldn't affect 
semantics), such as this one:

   language OverlappingInstances where
     instance C [Int]
     instance C [a]

Now we might not want to allow arbitrary language extensions in local 
"language" blocks, if any may have module-wide effects, but if necessary 
we could whitelist extensions that are allowed to be toggled locally. 
Also, this doesn't address the proposal's suggestion of per-constructor 
or per-field NoFieldSelectors; but I'm less convinced that is needed.

This could also solve a similar problem I have experienced, which is 
that TH declaration splices may need various specific language 
extensions for the declarations they generate. For example, both 
`persistent` and `optics` have TH code that reports errors if required 
extensions are not enabled. As a library author, I'd much rather enable 
extensions locally so my TH code works in more contexts and doesn't 
force users to enable otherwise unneeded extensions at the module level.

What do you think?

Adam


-- 
Adam Gundry, Haskell Consultant
Well-Typed LLP, https://www.well-typed.com/

Registered in England & Wales, OC335890
27 Old Gloucester Street, London WC1N 3AX, England



More information about the ghc-steering-committee mailing list