Notice that these functions are almost identical to the ones he wrote in order to build the Lenses.
This update functions can be composed easily:
updatePersonDetailsAddressLine1 : (String -> String) -> Model -> Model
updatePersonDetailsAddressLine1 fn model =
updatePersonDetails (updateAddress (updateLine1 fn)) model
On the other hand, nesting records is discouraged because it brings no benefit at all and it creates the problem of having to write extra boilerplate. He wouldn't even have the problem that lenses solve if he had just stuck to the "flat" record.
Btw: I think it was a great article! I didn't mean to sound too harsh criticizing; just wanted to clarify that point.
1. What you've written looks quite similar to the lenses approach.
2. I disagree that having nested records brings no benefit at all. What about when the types are generated on the backend so the shape of the model never goes out of sync across that boundary? For a non-trivial size application, I believe it's cheaper to use code generation to derive the type definitions, JSON encoders, and JSON decoders than it is to manually write all of it and try to make sure everyone on your team is disciplined enough to always make those changes.
It's not perhaps a surprise that they're similar to lenses; what you've written is a part of the lens hierarchy (they're setters). This is why people often say you end up just recreating the lens hierarchy anyways if you work with nested data structures a lot. Lenses just combine getters and setters (so they're just a pair of two functions; libraries like Monocle just give them a name instead of making them a literal pair).
They're nice if you have nested data structures that aren't records (e.g. naked product types a la "MyType Int Int Int").
But yes in general flat records are the way to go (but what about nested message types? Turns out that the lens hierarchy helps there too in the form of prisms. Or it would be nice if Elm had extensible union types so we could have flat message types too...)
The author himself admits that getting a value from a nested record is easy, so we don't need lenses to do that.
Setting a value from a nested record can be easily achieved using plain functions -- no need for a complex abstraction.
Notice that these functions are almost identical to the ones he wrote in order to build the Lenses.This update functions can be composed easily:
or, if you are feeling fancy: On the other hand, nesting records is discouraged because it brings no benefit at all and it creates the problem of having to write extra boilerplate. He wouldn't even have the problem that lenses solve if he had just stuck to the "flat" record.Btw: I think it was a great article! I didn't mean to sound too harsh criticizing; just wanted to clarify that point.