Excellent question! This is a tricky topic to discuss because the answer is not obvious.
Obvious answers include:
- Lenses
- Auto-generated setters
- New language syntax
I used to think think Elm should add language syntax to make nested record updates easier, but as I’ve spent more time with it I now realize that would be a design mistake. Relatedly, I’ve also come to view lenses as a such a huge mistake that if there were a way for the language to make it impossible to implement lens libraries, I would advocate for it. (Unfortunately, they are not possible to rule out.)
What I’ve realized over time is that the actual answer is this:
Nested record updates are a symptom, not the root problem itself.
Let’s go back to the original question:
Consider this model.
model = { foo = { bar = { baz = "hello world" } } }
I want to update
foo.bar.baz
. How should I do it?
When I read this part of the quote:
I want to update
foo.bar.baz
.
…I now have the same reaction as when I read something like this:
I want to mutate
window.foo
.
In both cases, if I were to respond “sure, here is how to do that” I would not be setting you up for success!
A better answer is “although the language permits doing this, it is so strongly discouraged as a technique that I think we should step back and reexamine the surrounding code to find a fundamentally better way to address your use case.”
There is no quick answer as to how to do this. It requires looking at the code in question and reexamining the relationships between the data model and the functions that operate on it. However, I think doing that is very much worthwhile - and if you’re interested in exploring that path, I think you might be surprised by the outcome!
I’d suggest starting a fresh thread with details on your particular situation (as opposed to foo
, bar
, etc.) - including the function that wants to do the nested record update, what its arguments are, what the application does, how the types work, and so on.
Good luck!