This post is part of our F# 8 series, in which we'll be digging into a few of the best features in the latest version of the language.
The problem with nested records 🤔
Over the years we have found one of the main pain points with records in F# is the awkward and verbose syntax that was needed to update values inside nested records. Let's consider this domain with nested records.
type Metadata = { LastUpdated : System.DateTime; Author: string }
type Document = { Title : string; Metadata : Metadata }
type Proposal = { MainDocument : Document; Revision : int }
Previously, if we wanted to write a function which took a proposal and updated the last updated time of its main document's metadata the code would look like this.
let setLastUpdatedOld proposal =
{ proposal with
MainDocument =
{ proposal.MainDocument with
Metadata =
{ proposal.MainDocument.Metadata with
LastUpdated = System.DateTime.Now } } }
As you can see, this is quite clunky. The main issues with this code are:
- It's quite hard to read and therefore to see that all we are doing is changing one deeply nested value, as opposed to substituting in a whole new record somewhere.
- It's time consuming and unpleasant to write.
The solution with F# 8 🥳
With F# 8, we have new syntax to make an update to a value in nested records. Here is what the function looks like using the new syntax.
let setLastUpdatedNew proposal =
{ proposal with MainDocument.Metadata.LastUpdated = System.DateTime.Now }
This is much easier to read and understand. It's also much faster and more pleasant to write.
Multiple nested record updates
As you might expect, it's also possible to make multiple updates at different levels of nesting with the nested record update syntax. Now we're just showing off... 😎
let multipleUpdates proposal =
{ proposal with
MainDocument.Title = "New title"
MainDocument.Metadata.LastUpdated = System.DateTime.Now }
Happy nesting 🐣
A solution to the problem of nested record updates has been a long time coming but we are glad that it's finally here. Thank you, F# team. And thank you for reading. 🙏