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

Record spread and never type #2737

Merged
merged 4 commits into from
Nov 17, 2022
Merged

Record spread and never type #2737

merged 4 commits into from
Nov 17, 2022

Conversation

toots
Copy link
Member

@toots toots commented Nov 13, 2022

This PR does two things:

Add an impossible never type when removing record methods

Example:

def f(x) =
 let y.{foo, gni} = x
 y
end

f : ('c.{foo : 'b, gni : 'a}) -> 'c.{foo? : never, gni? : never} = <fun>

This makes sure that the returned y value never has any foo or gni method, which is the runtime behavior.

Before that, the following was a correct function:

def f(x) =
  let y.{foo} = x
  y.foo + 1
end

f : ('b.{foo : 'a}) -> int = <fun>

Add syntactic sugar for record and record pattern spread

# This:
let y.{foo, gni} = x

# Can be written as:
let {foo, gni, ...y} = x

# This:
y = x.{foo = 123, gni = "aabb"}

# Can be written as:
y = {foo = 123, gni = "aabb", ...x}

These spread patterns are much more common nowadays and will help programmers being more confident in learning and understanding the language.

Ideally, we would like the spread to only apply to records (unit values with methods) and not other values, for instance:

x = 1.{foo = 123}
let { ...y } = x
y : { foo = 123}

However, I don't think that this is currently possible with the existing type system because we need to keep the root type universal in case this becomes wrapped into a function:

def f(x) =
  let {foo, gni, ...y } = x
   y
end

f : ('c.{foo : 'b, gni : 'a}) -> 'c.{foo? : never, gni? : never} = <fun>

There isn't a way currently to both say that y should be a record and that it should retain all the other methods from x. This might be possible with e.g. a constraint but I didn't want to enter that territory yet as I believe non-unit values with methods are still pretty advanced so why not let the advanced programmer know what they are doing?

@toots toots requested a review from smimram November 13, 2022 22:55
Copy link
Member

@smimram smimram left a comment

Choose a reason for hiding this comment

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

I think that this is good to go.

Small question: do we want to introduce a syntax to hide fields? Currently, this can be done by matching, but this is a bit heavy...

@toots
Copy link
Member Author

toots commented Nov 17, 2022

I think that this is good to go.

Small question: do we want to introduce a syntax to hide fields? Currently, this can be done by matching, but this is a bit heavy...

Thank! It'd be nice to have a syntax for it. This could be done is a different PR.

@toots toots enabled auto-merge (squash) November 17, 2022 04:35
@toots toots merged commit a7d78d2 into main Nov 17, 2022
@toots toots deleted the record-spread branch November 17, 2022 04:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants