F#: Overlapping fields in record types
A problem which has confused me for a while is how to create instances of record types whose fields overlap with another record defined further down in an F# file.
The most recently defined record seems to take precedence even if it has more fields than a record defined earlier and you don’t specify all of those fields in your record creation attempt.
For example, if I have the following two record types:
type Mark = { Value : string }
type SpecificMark = { Value: string; AnotherValue : int }
I thought it would be possible to create an instance of 'Mark' by doing this:
let mark = { Value = "mark" }
But what I actually got is the following compilation error:
No assignment given for field 'AnotherValue'
It turns out that you need to be more explicit about the fact that you want to create the 'Mark' record type.
Using the pre F# 1.9.16 syntax we would use the following object expression:
let mark = { new Mark with Value = "mark" }
But versions after that indicate that this syntax is deprecated and we need to do something more like this:
let mark = { new Mark with member self.Value = "mark" }
Which leads to the following error:
error FS0191: Only simple bindings of the form 'id = expr' can be used in construction expressions
This has also been mentioned on the hubfs forums although there is no suggestion as for why this syntax would be invalid - it seems like it should work to me.
Luckily there are a couple of other ways to get an instance of the 'Mark' type:
let (m:Mark) = { Value = "mark" }
let mark = {Value = "mark" } : Mark
Both of which require less typing anyway!
About the author
I'm currently working on short form content at ClickHouse. I publish short 5 minute videos showing how to solve data problems on YouTube @LearnDataWithMark. I previously worked on graph analytics at Neo4j, where I also co-authored the O'Reilly Graph Algorithms Book with Amy Hodler.