Hacker News new | past | comments | ask | show | jobs | submit login

You can think of a lens as just a pointer (like in C). They're not exactly like a pointer...you can't get or modify the address that it points to. But you can get and modify the thing that it points to, which is primarily how you use pointers in C.

But lenses can do things that pointers can't do. Namely, they can be composed. If you have a lens that points to a person's birth date

    dob :: Lens Person Date
...and a lens that points to a date's year field:

    year :: Lens Date Int
Then you can compose them like this:

    (dob . year) :: Lens Person Int
Normally it would be easy to retrieve the person's birth year with plain function composition. Lenses let you do that too. But setting the person's birth year is much more painful. This is where lenses shine.

    set (dob . year) 2004 person



Huh? In C, if you have a function from Person* to Date* and another function from Date* to Int*, you can compose them as well, and then use the resulting function to both get and set a person's birth year. The syntax is admittedly ugly, but I don't see any asymmetry between get and set.


Yes, I was talking about plain pointers (i.e. Person*), not functions of pointers.

Sure, you can do both get and set, but the simple syntax is precisely what we're going for here. Without lenses that set line would have looked like this:

    person { dob = (dob person) { year = 2004 } }
And this is just one level of nesting. Adding more levels gets really ugly. Also, lenses make it easy to do this kind of thing in a dynamic and generalized way.


"Functions of pointers" do seem an in-place equivalent for simple lenses. Pointers themselves less so - you can't compose pointers, and they take zero (when getting) or one (when setting) argument whereas a lens takes one or two.

Much like traditional getters and setters, lenses can offer more functionality though - for instance, an angle can be got and set in radians or degrees.


Yeah, that's interesting. I chose pointers because I was looking for a simple metaphor that imperative programmers would understand easily. If you ask random C programmer how to pass a single thing to a function such that you can both get and set it, pointers are the first thing that most of them will think of.


Pointers being symmetric was the point of his analogy. The asymmetry shows up when the setter is pure, returning a new version of the record instead of mutating it (as is the case in Haskell).

A getter is simple:

    x = s.foo.bar;
As is an impure setter:

    s.foo.bar = y;
But a non-mutating setter is a bit more work:

    Foo foo2 = s.foo;
    foo2.bar = y;
    S s2 = s;
    s2.foo = foo2;




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: