Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Split RecordDotSyntax into two extensions #405

Merged

Conversation

shayne-fletcher
Copy link
Contributor

@shayne-fletcher shayne-fletcher commented Feb 16, 2021

The functionality originally to be provided by the single language extension RecordDotSyntax is better provided by two orthogonal but related extensions OverloadedRecordSelection and OverloadedRecordUpdate.

See !4532(comment 330639) for context.

@phadej
Copy link
Contributor

phadej commented Feb 16, 2021

While it is not hard to deduce, I think proposal should be clear of the effects when only one extension is enabled.

Also if the only motivation is to get one part into 9.2 and the second later (into 9.4). Can't we wait with both for 9.4?

@shayne-fletcher
Copy link
Contributor Author

While it is not hard to deduce, I think proposal should be clear of the effects when only one extension is enabled.

Also if the only motivation is to get one part into 9.2 and the second later (into 9.4). Can't we wait with both for 9.4?

Actually we're angling to get both parts in 9.2 however, the OverloadedRecordUpdate part will require RebindableSyntax or updates will be in error. The restriction of requiring RebindableSyntax would get lifted in 9.4.

@shayne-fletcher
Copy link
Contributor Author

While it is not hard to deduce, I think proposal should be clear of the effects when only one extension is enabled.

Thanks for the feedback. I added this detail to section 2.1.

@Topsii
Copy link

Topsii commented Feb 16, 2021

Just curious the proposal says

We do not extend pattern matching, although it would be possible for P{foo.bar=Just x} to be defined.

Would this possible extension fall under OverloadedRecordSelection or OverloadedRecordUpdate?
From what I understand pattern matching uses getField instead of setField; hence it's OverloadedRecordSelection. On the other hand the linked comment and the proposal both state the expression e{lbl₁.lbl₂ = val} is equivalent to a use of setField. That confused me at first and might confuse others too if this proposal is ever extended to pattern matching.

Rephrasing it to

With the exception of pattern matching e{lbl₁.lbl₂ = val} is equivalent to e{lbl₁ = (e.lbl₁){lbl₂ = val}}

does not really make it easier to understand at first glance. Before the split into two extensions this complexity was rather elegantly hidden.

Will there still be a RecordDotSyntax extension (later on?) that implies both OverloadedRecordSelection and OverloadedRecordUpdate? Don't mind me though, I am probably not going to use this extension(s) in the near future.

@adamgundry
Copy link
Contributor

Also if the only motivation is to get one part into 9.2 and the second later (into 9.4).

I think this change is independently useful, even once both are implemented, because it means users have the option to switch on one feature without the other. There are enough changes coming regarding records (e.g. NoFieldSelectors, DuplicateRecordFields changes, the HasField stuff) that I think it makes sense to give users the flexibility to decide which pieces make up their preferred solution.

This may be particularly helpful when porting an existing codebase, because both extensions are non-conservative in different ways: OverloadedRecordSelection introduces new syntax but may break programs that do not use whitespace around . for composition, whereas OverloadedRecordUpdate re-purposes existing syntax in a way that may introduce ambiguity.

Can't we wait with both for 9.4?

It's not yet certain that OverloadedRecordUpdate (without-RebindableSyntax) will make 9.4, because the implementation is blocked on changing the design of setField via a proposal that I'm still writing. Whereas OverloadedRecordSelection is close to being ready now, and there is demand for it even without update, so it would be a shame to delay.

@adamgundry
Copy link
Contributor

We do not extend pattern matching, although it would be possible for P{foo.bar=Just x} to be defined.

Would this possible extension fall under OverloadedRecordSelection or OverloadedRecordUpdate?

I think neither, because it isn't overloaded. The data constructor determines which type is meant. So it would really be a small syntactic extension to record pattern-matching syntax. But in any case that would require a separate proposal.

@phadej
Copy link
Contributor

phadej commented Feb 16, 2021

@adamgundry so the @shayne-fletcher comment

.. part will require RebindableSyntax or updates will be in error. The restriction of requiring RebindableSyntax would get lifted in 9.4.

is a white lie?

@adamgundry
Copy link
Contributor

@phadej I'd rather say it is a plausible prediction, just not a guarantee. 😉 I'm fairly optimistic we can hit 9.4, but it depends on whether my upcoming proposal gets mired in debate and whether the implementation hits any more blockers.

@shayne-fletcher shayne-fletcher force-pushed the amend-record-dot-syntax branch 2 times, most recently from 45926fd to ed06974 Compare February 16, 2021 14:56
@phadej
Copy link
Contributor

phadej commented Feb 16, 2021

Then I'll ask for OverloadedRecordUpdate part to not be merged for 9.2 if its future is dependent on yet unwritten proposal. This proposal doesn't specify the intermediate state, and as a GHC user I'd prefer it to not exist.

At the very least the intermediate state should be brought to the committee for discussion.

@shayne-fletcher shayne-fletcher force-pushed the amend-record-dot-syntax branch 2 times, most recently from 48db6e8 to d2ca25d Compare February 16, 2021 15:59
@ndmitchell
Copy link
Contributor

I wonder about the names of the extensions. I think RecordDotSelection might be a better name than OverloadedRecordSelection, because we don't overload the existing record selection, we overload the new record dot, in the way it was always suggested. In contrast, OverloadedRecordUpdate seems to capture that one well. Maybe the fact they are different is annoying enough they should both be Overloaded... or both be RecordDot....

Then I'll ask for OverloadedRecordUpdate part to not be merged for 9.2 if its future is dependent on yet unwritten proposal.

It's future might change based on future proposals. But as it stands currently, it's based on accepted but not yet fully implemented proposals. However, the RecordDotSyntax proposal lays out how it interacts with RebindableSyntax, so that part is entirely and accepted clear and fully implemented. (That isn't to say that one half shouldn't be marked more experimental, or even be hidden from users entirely.)

I note that RecordDotSyntax isn't in this proposal as an extension. Should it be? I know Adam is keen to give users a toolbox of lots of little pieces of syntax that can be put together to craft working records. I always felt that RecordDotSyntax should imply NoFieldSelectors. Or do we defer a comprehensive "records work" extension as a bundling of ~3 extensions for a future proposal?

@simonpj
Copy link
Contributor

simonpj commented Feb 16, 2021

I think it would be helpful to summarise the changes embodied by this PR.

@shayne-fletcher
Copy link
Contributor Author

shayne-fletcher commented Feb 16, 2021

I think it would be helpful to summarise the changes embodied by this PR.

  • Section 2.1 Language Extensions
    • Remove RecordDotSyntax
    • Add OverloadedRecordSelection OverloadedRecordDot, OverloadedRecordUpdate
      • Define OverloadedRecordSelection OverloadedRecordDot effects
      • Define OverloadedRecordUpdate effects
  • Section 2.1.1 Syntax
    • Change occurrence of RecordDotSyntax to OverloadedRecordUpdate
  • Section 2.1.2 Precedence
    • Provide clarifying text for interpretations of f M.n.x and f M.N.x
  • Section 2.3.1 Lexer
    • Add a sentence explaining '.' in a qualified name is never a field selection
  • Section 2.3.2 Parsing
    • Remove qvarid from field production
  • Global:
    • Replace occurences of "RecordDotSyntax" with "the extensions"

@shayne-fletcher
Copy link
Contributor Author

You can view the rendered version here.

@shayne-fletcher
Copy link
Contributor Author

shayne-fletcher commented Feb 16, 2021

RecordDotSelection might be a better name than OverloadedRecordSelection

I understood the motivation for OverloadedRecordSelection is that getField can be overloaded. I also believe @adamgundry is enamoured of having a set of similarly named extensions e.g. OverloadedLabels, and so on.

In any case, regarding specific names, let me know and I'll adjust... I'm easy!

@adamgundry
Copy link
Contributor

I don't feel terribly strongly about naming, but there is precedent for Overloaded... extensions meaning "interpret this piece of syntax via a typeclass". In some cases (OverloadedLists, OverloadedStrings) the syntax is already valid and it is generalised, while in the case of OverloadedLabels the syntax is valid only when the extension is enabled. Perhaps OverloadedRecordDot?

I note that RecordDotSyntax isn't in this proposal as an extension. Should it be? I know Adam is keen to give users a toolbox of lots of little pieces of syntax that can be put together to craft working records. I always felt that RecordDotSyntax should imply NoFieldSelectors. Or do we defer a comprehensive "records work" extension as a bundling of ~3 extensions for a future proposal?

I wondered about this. I do generally prefer the approach of defining small orthogonal extensions first, then specifying larger features as the conjunction of such extensions. Moreover my feeling is that RecordDotSyntax shouldn't be added as an implemented extension until we have OverloadedRecordUpdate fully implemented. So I'd be inclined to defer, and leave open the possibility of changing the set of implied extensions via another proposal.

@chreekat
Copy link

I think it makes sense to give users the flexibility to decide which pieces make up their preferred solution.

As a user, the presence of many fine grained possibilities doesn't always help me, because I'm not paged in to the nuanced trade-offs.

I wondered about this. I do generally prefer the approach of defining small orthogonal extensions first, then specifying larger features as the conjunction of such extensions.

This, however, makes sense. As long as we end up at a satisfying whole, I agree that it's good to build up pieces incrementally. So I hope this proposal is seen as an enabler for RecordDotSyntax rather than a replacement.

@danidiaz
Copy link

If OverloadedRecordSelection is enabled in a module but OverloadedRecordUpdate is not, will type-changing record updates be possible?

@adamgundry
Copy link
Contributor

If OverloadedRecordSelection is enabled in a module but OverloadedRecordUpdate is not, will type-changing record updates be possible?

Yes, my understanding is that when OverloadedRecordUpdate is disabled, a record update expression will be type-checked in the usual way, i.e. the fields will need to uniquely determine a single record datatype but type-changing update of that datatype will be possible.

@shayne-fletcher
Copy link
Contributor Author

@nomeata I'd like to formally ask to turn consideration of this amendment over to the committee now please.

@nomeata nomeata changed the title Split RecordDotSyntax into two extensions Split RecordDotSyntax into two extensions (under review) Feb 20, 2021
@nomeata nomeata added the Pending committee review The committee needs to evaluate the proposal and make a decision label Feb 20, 2021
@nomeata nomeata added Pending shepherd recommendation The shepherd needs to evaluate the proposal and make a recommendataion and removed Pending committee review The committee needs to evaluate the proposal and make a decision labels Feb 20, 2021
@shayne-fletcher
Copy link
Contributor Author

shayne-fletcher commented Feb 24, 2021

I am not sure how this is supposed to work. Consider the following example:

{-# LANGUAGE OverloadedRecordDot, DuplicateRecordFields #-}
data T = T { x :: Int }
data S = S { x :: Int }

f a = a { x = 2 }

The proposal says that this should mean what it means in Haskell'98. So, what is the type of f?

It requires disambiguation

    • Record update is ambiguous, and requires a type signature
    • In the expression: a {x = 2}
      In an equation for ‘f’: f a = a {x = 2}
  |
5 | f a = a { x = 2 }
  |       ^^^^^^^^^^^

@simonpj
Copy link
Contributor

simonpj commented Feb 24, 2021

I am not sure how this is supposed to work.

Your example does not involve any dots, so it'd be unaffected by this proposal, no?

@adamgundry
Copy link
Contributor

To expand a bit on the motivation, a couple of concrete cases where the split would be useful:

  • If I have a codebase that relies heavily on type-changing record updates (which are allowed with traditional record update), I can't use OverloadedRecordUpdate because it does not support type-changing update. Enabling the extension will cause my programs to stop type-checking. However I can enable and use OverloadedRecordDot without a problem.
  • If I have a codebase that makes heavy use of function compositions without whitespace, I can't turn on OverloadedRecordDot because it changes the parser. But it would be fine to use OverloadedRecordUpdate.

These are meaningfully distinct features, even though they were originally proposed together as one RecordDotSyntax extension. Given that we have various records-related changes coming soon (DuplicateRecordFields changes, NoFieldSelectors, my plans to propose changing HasField, ...) I think it makes sense to add the individual pieces first, then when we have a bit more experience of using them, figure out how it would be best to group them together.

@yav
Copy link
Contributor

yav commented Feb 24, 2021

OK, I am confused about the myriad of record extensions:

  • I thought that OverloadedRecordDot implies DuplicateRecordFields, but I guess it does not. So I guess OverlodedRecordDot is just about how to desugar x.r and has nothing to do with datatypes (e.g., there is nothing about generating instances for the Has) classes. Is that correct?

On the topic of splitting the two, I agree it would be useful to do so, but I'd like to raise the question if we should have OverloadedRecordUpdate at all. In particular, it changes the meaning of current notation (x { f = 2 }) to something more restrictive. Furthermore the loss of generality is important---type changing record updates are quite useful. As such, I doubt this would ever be an extension that we'd want turned on by default. So it would never really be part of a unified language, and my understanding is that this is something we'd like to avoid. Perhaps a better design would be to have a different notation for this kind of monomorphic record update.

@shayne-fletcher
Copy link
Contributor Author

shayne-fletcher commented Feb 24, 2021

OK, I am confused about the myriad of record extensions:

  • I thought that OverloadedRecordDot implies DuplicateRecordFields, but I guess it does not. So I guess OverlodedRecordDot is just about how to desugar x.r and has nothing to do with datatypes (e.g., there is nothing about generating instances for the Has) classes. Is that correct?

You are correct.

On the topic of splitting the two, I agree it would be useful to do so,

Great!

but I'd like to raise the question if we should have OverloadedRecordUpdate at all. In particular, it changes the meaning of current notation (x { f = 2 }) to something more restrictive. Furthermore the loss of generality is important---type changing record updates are quite useful. As such, I doubt this would ever be an extension that we'd want turned on by default. So it would never really be part of a unified language, and my understanding is that this is something we'd like to avoid. Perhaps a better design would be to have a different notation for this kind of monomorphic record update.

Sorry, this was debated when the original proposal was considered and accepted. I don't think it falls into the category of things that are being considered with respect to this amendment. [BTW @yav I draw your attention to 7.6 Should a new update syntax be added?]

@yav
Copy link
Contributor

yav commented Feb 24, 2021

@shayne-fletcher can you point me to something that outlines what's the long term plan for the language? Which of these futures are we aiming for:

  1. Make OverloadedUpdate part of the language standard, thus loosing the ability to do type changing update
  2. Make Language pragmas part of the actual language specification, and so syntax means different things in different modules depending on the pragmas

Perhaps there is another option, I'd be interested to hear. There was a lot of pressure to accept the original proposal, and most of the discussion was about the syntactic issues to do with . being used as both and operator and a record selector, and I don't recall discussing this particular topic.

@shayne-fletcher
Copy link
Contributor Author

@shayne-fletcher can you point me to something that outlines what's the long term plan for the language? Which of these futures are we aiming for:

  1. Make OverloadedUpdate part of the language standard, thus loosing the ability to do type changing update
  2. Make Language pragmas part of the actual language specification, and so syntax means different things in different modules depending on the pragmas

Perhaps there is another option, I'd be interested to hear. There was a lot of pressure to accept the original proposal, and most of the discussion was about the syntactic issues to do with . being used as both and operator and a record selector, and I don't recall discussing this particular topic.

Sadly I myself simply can't do this for you @yav , I must defer to others. I do think you have posed very good questions and I too look forward to hearing what can be said in response to them!

@ndmitchell
Copy link
Contributor

This point was discussed at length. But GitHub doesn't support the length the conversation grew to, so it's probably infeasible to point you at where. There is reference to it as a drawback in https://ghc-proposals.readthedocs.io/en/latest/proposals/0282-record-dot-syntax.html#id13.

On the topic of splitting the two, I agree it would be useful to do so, but I'd like to raise the question if we should have OverloadedRecordUpdate at all. In particular, it changes the meaning of current notation (x { f = 2 }) to something more restrictive. Furthermore the loss of generality is important---type changing record updates are quite useful.

Restricting record updates is useful to get decent type checking. Otherwise, given unconstrained types, expressions like x{f = 2, g = 3} would end up with ambiguous types in the middle, as they desugar to two setField calls. I would personally happily (gladly) sacrifice polymorphic update (which I used ever other year or so) for duplicate field names (which I would use every day).

We could certainly come up with a new syntax for monomorphic vs polymorphic desugaring. And furthermore, I recommend \Foo{..} -> Foo{f = 2, ..} as the polymorphic variant 😉.

As to whether there is a way to have polymorphic update, but enough type constraints to make it have decent inference, that's connected to this proposal, but slightly different. If you switch out setField with something that allows type changing update, it would work. Given the RebindableSyntax plus this proposal, we'd have the freedom to experiment.

@danidiaz
Copy link

If a typeclass like SetField exists, the "getter dot" of OverloadedRecordSelection is enough to emulate a form of nested record update:

class SetField (n :: Symbol) r v | n r -> v where
    modifyField :: (v -> v) -> r -> r

newtype Setter a b = Setter ((b -> b) -> a)

(.=) :: Setter a b -> b -> a
Setter f .= b = f (const b)

-- Setters in the original record turn into getters of the Setter newtype
instance SetField n b c => HasField n (Setter a b) (Setter a c) where
    getField (Setter f) = Setter (f . modifyField @n)

set :: a -> Setter a a
set a = Setter (\f -> f a)

It could be used like this:

person' = (set person).address.number .= 4

Annoyingly, it seems to require UndecidableInstances.

@simonpj
Copy link
Contributor

simonpj commented Feb 25, 2021

@yav asks which of these we are aiming for

  1. Make OverloadedUpdate part of the language standard, thus loosing the ability to do type changing update

  2. Make Language pragmas part of the actual language specification, and so syntax means different things in different modules depending on the pragmas

That particular question is a reasonable one, but it could be asked of many other extensions, including OverloadedStrings, OverloadedLists etc, all of which change the meaning of existing syntax. I'm not sure we need answer it now.

About overloaded, non-type-changing record update

  • We've already accepted it for RecordDotSyntax. Of course, no decision is irrevocable. We can always change our minds and decide that it should not be part of RecordDotSyntax, but that should be another proposal.

  • In a way, this current small proposal makes a helpful step in that direction: by separating OverloadedRecordDot and OverloadedRecordUpdate it allows you to have r.x while still having the non-overloaded, type-changing record update. That should be useful for those who want type-changing, but not overloaded, record update, Iavor perhaps among them.

    Perhaps we will then gain experience about the pros and cons, which can inform future decisions. It's really difficult to anticipate what will matter and what won't; better to find out from experience.

Comment on lines 503 to 509
7.7 Why two extensions and not just one?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Having two extensions provides fine grained control. For example, one
can enable the use of ``.`` for field selection without affecting
record updates. Conversely, one can enable overloaded record updates
without giving ``.`` new meaning.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like a pretty weak motivation to have two extensions. After all, extensions have a cost, so we must get a real benefit for that cost.

That being said, my understanding of the thread is that there are, indeed, stronger motivations. At least the fact that the record update syntax is not backward compatible should be brought up. I'm not entirely sure I managed to understand what motivated everyone involved. But it's alright: that's what this section is about, it should document the motivations which have accumulated through the threads (and objections as well). That would be really helpful!

@simonpj
Copy link
Contributor

simonpj commented Mar 1, 2021

Thanks Arnaud. I think the alternatives and their motivations are pretty straightforward:

  1. Add two extensions, as proposed. Pro: flexibility for people like Iavor who want type-changing update, but would still like dot-notation. Pro: orthogonal things are controlled by separate flags. Con: each has to be documented separately: two flags with one para each, instead of one flag with two paras. (The implementation cost is zero: it's only a question of which flag to test.)

  2. Add one extension (OverloadedRecordFields, say) to do what OverloadedRecordDot and OverloadedRecordUpdate to in this proposal. Pro: only one extension. Con: Iavor and others might want dot-notation, but not want to give up type-changing update.

  3. Use RecordDotSyntax, and be prepared to change what it means (e.g. add NoFieldSelectors) later. Pro: only one extension. Con: changing the meaning of an extension will break programs.

There is nothing deep here. I don't think it matters much which we choose, but we should choose. My own recommendation is (1), but if there is a consensus for (2) or (3), or someone wants to suggest another alternative, that would be equally fine.

@arybczak
Copy link

arybczak commented Mar 1, 2021

This point was discussed at length. But GitHub doesn't support the length the conversation grew to, so it's probably infeasible to point you at where. There is reference to it as a drawback in https://ghc-proposals.readthedocs.io/en/latest/proposals/0282-record-dot-syntax.html#id13.

On the topic of splitting the two, I agree it would be useful to do so, but I'd like to raise the question if we should have OverloadedRecordUpdate at all. In particular, it changes the meaning of current notation (x { f = 2 }) to something more restrictive. Furthermore the loss of generality is important---type changing record updates are quite useful.

Restricting record updates is useful to get decent type checking. Otherwise, given unconstrained types, expressions like x{f = 2, g = 3} would end up with ambiguous types in the middle, as they desugar to two setField calls. I would personally happily (gladly) sacrifice polymorphic update (which I used ever other year or so) for duplicate field names (which I would use every day).

We could certainly come up with a new syntax for monomorphic vs polymorphic desugaring. And furthermore, I recommend \Foo{..} -> Foo{f = 2, ..} as the polymorphic variant wink.

As to whether there is a way to have polymorphic update, but enough type constraints to make it have decent inference, that's connected to this proposal, but slightly different. If you switch out setField with something that allows type changing update, it would work. Given the RebindableSyntax plus this proposal, we'd have the freedom to experiment.

There is no need to come up with a different syntax, type-changing updates with good type inference are possible.

optics-core-0.4 has them via generics with no special compiler support (though it exploits dysfunctional dependencies in order to get them), so there is no reason not to have them in GHC proper (@adamgundry is working on a proposal to extend SetField to allow them, based on the experience we gained with optics).

Below snippet demonstrates that you can have type-changing updates compatible with overloaded fields with the same type-inference properties as the classic record update syntax.

type-changing.hs
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE NamedWildCards #-}
{-# LANGUAGE PartialTypeSignatures #-}
{-# LANGUAGE TypeApplications #-}
module TypeChanging where

import GHC.Generics (Generic)
import Optics.Core

data Pet = Pet
  { name :: String
  } deriving (Show, Generic)

data User ph a = User
  { name :: String
  , age  :: a
  , pet  :: Maybe Pet
  } deriving (Show, Generic)

-- signature inferrable by ghc, can be written down
general :: ( Num b1
           , GField "name" s3 s1 a2 [a3]
           , GField "age" s1 s2 a1 b1
           , GField "pet" s2 b2 a4 (Maybe a5)
           ) => s3 -> b2
general user = user & gfield @"name" .~ []
                    & gfield @"age"  .~ 23
                    & gfield @"pet"  .~ Nothing


-- ../type-changing.hs:33:22: warning: [-Wpartial-type-signatures]
--     • Found type wildcard ‘_ph’ standing for ‘a’
--       Where: ‘a’ is a rigid type variable bound by
--                the inferred type of infer_output :: User a a1 -> User a2 Integer
--                at ../type-changing.hs:34:1-22
--     • In the type signature: infer_output :: User _ph _a -> _output
--    |
-- 33 | infer_output :: User _ph _a -> _output
--    |                      ^^^
--
-- ../type-changing.hs:33:26: warning: [-Wpartial-type-signatures]
--     • Found type wildcard ‘_a’ standing for ‘a1’
--       Where: ‘a1’ is a rigid type variable bound by
--                the inferred type of infer_output :: User a a1 -> User a2 Integer
--                at ../type-changing.hs:34:1-22
--     • In the type signature: infer_output :: User _ph _a -> _output
--    |
-- 33 | infer_output :: User _ph _a -> _output
--    |                          ^^
--
-- ../type-changing.hs:33:32: warning: [-Wpartial-type-signatures]
--     • Found type wildcard ‘_output’ standing for ‘User a2 Integer’
--       Where: ‘a2’ is a rigid type variable bound by
--                the inferred type of infer_output :: User a a1 -> User a2 Integer
--                at ../type-changing.hs:34:1-22
--     • In the type signature: infer_output :: User _ph _a -> _output
--    |
-- 33 | infer_output :: User _ph _a -> _output
infer_output :: User _ph _a -> _output
infer_output = general

-- ../type-changing.hs:36:16: warning: [-Wpartial-type-signatures]
--     • Found type wildcard ‘_input’ standing for ‘User a a1’
--       Where: ‘a’, ‘a1’ are rigid type variables bound by
--                the inferred type of infer_input :: User a a1 -> User a2 Integer
--                at ../type-changing.hs:37:1-21
--     • In the type signature: infer_input :: _input -> User _ph _a
--    |
-- 36 | infer_input :: _input -> User _ph _a
--    |                ^^^^^^
--
-- ../type-changing.hs:36:31: warning: [-Wpartial-type-signatures]
--     • Found type wildcard ‘_ph’ standing for ‘a2’
--       Where: ‘a2’ is a rigid type variable bound by
--                the inferred type of infer_input :: User a a1 -> User a2 Integer
--                at ../type-changing.hs:37:1-21
--     • In the type signature: infer_input :: _input -> User _ph _a
--    |
-- 36 | infer_input :: _input -> User _ph _a
--    |                               ^^^
--
-- ../type-changing.hs:36:35: warning: [-Wpartial-type-signatures]
--     • Found type wildcard ‘_a’ standing for ‘Integer’
--     • In the type signature: infer_input :: _input -> User _ph _a
--    |
-- 36 | infer_input :: _input -> User _ph _a
infer_input :: _input -> User _ph _a
infer_input = general

@shayne-fletcher shayne-fletcher force-pushed the amend-record-dot-syntax branch 3 times, most recently from 39fae1e to 59d5cfe Compare March 4, 2021 15:45
@simonpj
Copy link
Contributor

simonpj commented Mar 8, 2021

Just to close the loop on this proposal:

  • The committee accepts this modification of the original proposal. Thank you for making various modifications in response to our suggestions.

  • There is now work (led by Adam Gundry) on improving OverloadedRecordUpdate, so we'd like the user manual to flag that part of the design as experimental and liable to change.

Please merge the change into the original proposal.

I understand that the implementation will be out in GHC 9.2.

Thank you, Shayne, Neil, Adam, for doing this work!

@nomeata
Copy link
Contributor

nomeata commented Mar 8, 2021

@shayne-fletcher , can I press the merge button, or is there still something to be done here?

@shayne-fletcher
Copy link
Contributor Author

@shayne-fletcher , can I press the merge button, or is there still something to be done here?

Thanks @nomeata , this is good to merge.

@nomeata nomeata merged commit e67b537 into ghc-proposals:master Mar 9, 2021
@nomeata nomeata added Accepted The committee has decided to accept the proposal and removed Pending shepherd recommendation The shepherd needs to evaluate the proposal and make a recommendataion labels Mar 9, 2021
@int-index int-index changed the title Split RecordDotSyntax into two extensions (under review) Split RecordDotSyntax into two extensions Mar 11, 2021
@nomeata nomeata added the Implemented The proposal has been implemented and has hit GHC master label Jul 5, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Accepted The committee has decided to accept the proposal Implemented The proposal has been implemented and has hit GHC master
Development

Successfully merging this pull request may close these issues.

None yet