PureScript: Nested Record Updates
When compiler version 0.10.6 is released, it will include a syntax for nested record updates.
Problem
Before this change, if we have a nested record structure such as:
r = { val: -1
, level1: { val: -1
, level2: { val: -1 }
}
}
To update .level1.val
we’d have to write something like this:
r' = r { level1 = r.level1 { val = 1 } }
This is fairly annoying to write: we need to mention both r
and level1
twice. With even more nesting it just gets worse:
r'' = r { level1 = r.level1 { level2 = r.level1.level2 { val = 2 } } }
Solution
With the new syntax, the following equivalent expressions are supported:
r' = r { level1 { val = 1 } }
r'' = r { level1 { level2 { val = 2 } } }
To update all the val
fields it’d look like this:
r' = r { val = 0
, level1 { val = 1
, level2 { val = 2 }
}
}
Evaluation
In the previous example we updated an object computed by the expression r
- which is just a variable. However if we compute a record by some more complicated expression and then try to update, we wouldn’t just blindly substitute the expression in:
-- `f r` has been repeated
s = (f r) { level1 = (f r).level1 { val = 1 } }
Instead we would first compute f r
and refer to the result twice:
s' = let fr = f r in fr { level1 = fr.level1 { val = 1 } }
When the compiler desugars nested record updates, to prevent reevaluating the object expression, it introduces a let
binding like the previous example.