Relax restrictions on record deconstruction
We define two record types and declared A point instance.
type Point = {x:int;y:int}
type Vector = {x:int;y:int}
let p = {x=1;y=2}:Point
We extract some fields from p
let {x=xx;y=yy} = p
I propose When a pattern matches a record, the specific type of the record is not matched(it can be any record), only the members of the record are matched(name and type). We remove the restriction on the type of the record literal on the left, Because it is used once and was discarded. it is a temporary construct that is useful only for the newly created fields instance xx and yy.
The existing way of approaching this problem in F# is We must provide the type of the record literal on the left,
let ({x=xx;y=yy}:Point) = p
Pros and Cons
The advantages of making this adjustment to F# are The code is more concise and shorter. No additional type information is required.
The disadvantages of making this adjustment to F# are ...
Extra information
Estimated cost (XS, S, M, L, XL, XXL):
Related suggestions: (put links to related suggestions here)
Affidavit (please submit!)
Please tick this by placing a cross in the box:
- [x] This is not a question (e.g. like one you might ask on stackoverflow) and I have searched stackoverflow for discussions of this issue
- [x] I have searched both open and closed suggestions on this site and believe this is not a duplicate
- [x] This is not something which has obviously "already been decided" in previous versions of F#. If you're questioning a fundamental design decision that has obviously already been taken (e.g. "Make F# untyped") then please don't submit it.
Please tick all that apply:
- [ ] This is not a breaking change to the F# language design
- [ ] I or my company would be willing to help implement and/or test this
For Readers
If you would like to see this issue implemented, please click the :+1: emoji on this issue. These counts are used to generally order the suggestions by engagement.
To define a construct, like a function or a member, F# has a feature called ducktyping with SRTP. Through SRTP, you can define a function that takes any record that defines a certain field, like x in your example.
So, what you’re proposing here is already possible and often applied in many libraries. And just as you propose, the argument isn’t really a record, it’s just any type (record) that has a member or field as you suggest.
The only difference is that it is way more flexible and can be applied to any type, record, discriminated union.
The existing way of approaching this problem in F# is We must provide the type of the record literal on the left,
Yes. That's because F# enforces static type safety. This means that F# must know statically what the types are. As far as I know, removing type safety by somehow magically saying "any type that has field x should match this" introduces type leniency, which goes against F#'s core principles.
It's even in your suggestion, "Make F# untyped", this, I think, falls into the same ballpark:
If you're questioning a fundamental design decision that has obviously already been taken (e.g. "Make F# untyped") then please don't submit it.
I'd suggest to stick to SRTP, it allows things to be untyped, but the compiler can inline such functions without violating type safety.
While it's understandable that the following code should be expected to compile, since it's known that p is a Point:
type Point = {x:int;y:int}
type Vector = {x:int;y:int}
let p = {x=1;y=2}:Point
let {x=xx;y=yy} = p
...but this is actually a flow-based type system by another name. The general pattern in F# is to be very explicit about what something is when type inference doesn't resolve, or resolves to something different. This lets you define that place where you're explicit once and utilize that later, but it opens up a whole other can of worms around behavior, namely around what else can influence what the type of something is later in the code.
The underlying problem here is that we check the pattern of a let pat = expr before we check the expr. Arguably this is wrong. However it can't be changed now.
I could see some future revision of F# making a whole set of different decisions about records, placing them much closer to JSON data. However that's beyond the scope of these suggestions.
I'll close this since we can't realistically do it without a breaking change.