
On Thu, Aug 2, 2012 at 9:00 AM, Jonathan Geddes
Richard O'Keefe Said:
Ouch! And that's not even very deeply nested. Imagine 4 or 5 levels deep. It really makes Haskell feel clunky next to `a.b.c.d = val` that you see in other languages.
I was taught that this kind of thing violates the Law of Demeter and that an object should not be mutating the parts of an acquaintance's parts, but should ask the acquaintance to do so. I'd say that a.b.c.d = val is at the very least a sign that some encapsulation did not happen.
Absolutely! But in Haskell how do you do the asking? I guess that's what I'm proposing is a built in way of doing just that! I'm shooting for as-easy-as the built in getters.
I consider that a strength of the lens approach. If I say 'set (a.b.c.d) 42 record', 'a', 'b' etc. don't have to be record fields, I can swap them out for other lenses later on. I can also easily precompose, e.g. 'setThis = a . b; setThat = b . c' and encourage people to use the composed ones (or require via export lists). This corresponds to "asking" in that it introduces a point of abstraction where I can change all access / modification in one place, or a module can retain control by only exporting the composed version.
Erik Hesselink said:
Isn't this exactly the problem solved by all the lens packages?
Yes it is. I think the existence of these packages along with all the proposals to change records is an indication that something is missing from the language as a whole. What I'm proposing is that the language give you something that is lightweight and easy to use to address this issue. You can still use lenses on top of all of this.
I put up a record suggestion a while back that was in two parts, one was a default lens implementation and the ability to write 'deriving (Lens)' on a record to create the lenses. The other was some magic syntax to make it easier to type in the lens names. Actually it was mostly magic syntax, since 'deriving (Lens)' pretty much speaks for itself, though you'd need to include a default lens implementation in the stdlib. I think that's a good idea anyway, but on the other hand people are still innovating in lens land. But back on the first hand again, threat of inclusion in the stdlib might force a much-needed consolidation and polishing in the lens world (pun honestly not intended). Automatically creating something (semantic editors) which isn't lenses but makes it easier to write lenses is an interesting compromise, though it is really convenient how lenses let you compose the getter and setter together. But I've found that even one line of boilerplate for each record field is already enough to discourage me from writing one for each record field since it only pays off if there's a nested update.
If I remember correctly, one of the problems with lenses is that they cannot support polymorphic updates (updates which change a type variable of the data). SEC functions, on the other hand support polymorphic updates.
This has been solved, yes? I haven't gotten time to investigate fully, but: http://hackage.haskell.org/package/lens-family I should look into it and update the lensy-record proposal if they're appropriate. Though it would be nice to see feedback on it, point out a fatal flaw, or at least someone could mention they read it, so I can know whether or not it's worth spending the time: http://hackage.haskell.org/trac/ghc/wiki/Records/SyntaxDirectedNameResolutio...