Representation of lenses

Hi, I'm planning on discussing lenses with some colleagues shortly so I'm consolidating some of my notes into a coherent story. At one point I found myself describing lenses as a way of packaging up a getter and a setter into a single thing. However, this raises the question: why not just use a pair (getter, setter)? More precisely, I believe that the types (a -> s, s -> a -> a) and (forall f. Functor f => (s -> f s) -> a -> f a) are isomorphic. Is that right? I see that one advantage of the lens type is that you can use (.) to compose them since they're just functions, but that doesn't bother me much and it seems I could define another operator to compose (getter, setter) lenses and the rest of the machinery would work either way. It's also possible that you can't get the full generality of (forall f. (s -> f t) -> a -> f b) lenses with getter/setter pairs, although I haven't worked through the details yet so don't know either way. So, my question is: what is the advantage of representing lenses in the way that they are? Many thanks, David

You need to sign up for it, but this is a phenomenal talk by simon peyton jones describing the idea behind lenses the way he understood it. https://skillsmatter.com/skillscasts/4251-lenses-compositional-data-access-a... On Tue, Jan 27, 2015 at 12:18 PM, David Turner < dct25-561bs@mythic-beasts.com> wrote:
Hi,
I'm planning on discussing lenses with some colleagues shortly so I'm consolidating some of my notes into a coherent story. At one point I found myself describing lenses as a way of packaging up a getter and a setter into a single thing. However, this raises the question: why not just use a pair (getter, setter)? More precisely, I believe that the types (a -> s, s -> a -> a) and (forall f. Functor f => (s -> f s) -> a -> f a) are isomorphic. Is that right?
I see that one advantage of the lens type is that you can use (.) to compose them since they're just functions, but that doesn't bother me much and it seems I could define another operator to compose (getter, setter) lenses and the rest of the machinery would work either way.
It's also possible that you can't get the full generality of (forall f. (s -> f t) -> a -> f b) lenses with getter/setter pairs, although I haven't worked through the details yet so don't know either way.
So, my question is: what is the advantage of representing lenses in the way that they are?
Many thanks,
David _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

Thanks, I'll give that a watch.
On 27 Jan 2015 17:23, "Charles Durham"
You need to sign up for it, but this is a phenomenal talk by simon peyton jones describing the idea behind lenses the way he understood it.
https://skillsmatter.com/skillscasts/4251-lenses-compositional-data-access-a...
On Tue, Jan 27, 2015 at 12:18 PM, David Turner < dct25-561bs@mythic-beasts.com> wrote:
Hi,
I'm planning on discussing lenses with some colleagues shortly so I'm consolidating some of my notes into a coherent story. At one point I found myself describing lenses as a way of packaging up a getter and a setter into a single thing. However, this raises the question: why not just use a pair (getter, setter)? More precisely, I believe that the types (a -> s, s -> a -> a) and (forall f. Functor f => (s -> f s) -> a -> f a) are isomorphic. Is that right?
I see that one advantage of the lens type is that you can use (.) to compose them since they're just functions, but that doesn't bother me much and it seems I could define another operator to compose (getter, setter) lenses and the rest of the machinery would work either way.
It's also possible that you can't get the full generality of (forall f. (s -> f t) -> a -> f b) lenses with getter/setter pairs, although I haven't worked through the details yet so don't know either way.
So, my question is: what is the advantage of representing lenses in the way that they are?
Many thanks,
David _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

One significant reason is that the getter/setter pair doesn't support
efficient update operations in a nested structure. Updating the
hundredth element of a list would require getting it, applying a
function to it, and then setting it. With the fancy type and magic
tricks, you only need to dig down to the right place once.
On Tue, Jan 27, 2015 at 1:09 PM, David Turner
Thanks, I'll give that a watch.
On 27 Jan 2015 17:23, "Charles Durham"
wrote: You need to sign up for it, but this is a phenomenal talk by simon peyton jones describing the idea behind lenses the way he understood it.
https://skillsmatter.com/skillscasts/4251-lenses-compositional-data-access-a...
On Tue, Jan 27, 2015 at 12:18 PM, David Turner
wrote: Hi,
I'm planning on discussing lenses with some colleagues shortly so I'm consolidating some of my notes into a coherent story. At one point I found myself describing lenses as a way of packaging up a getter and a setter into a single thing. However, this raises the question: why not just use a pair (getter, setter)? More precisely, I believe that the types (a -> s, s -> a -> a) and (forall f. Functor f => (s -> f s) -> a -> f a) are isomorphic. Is that right?
I see that one advantage of the lens type is that you can use (.) to compose them since they're just functions, but that doesn't bother me much and it seems I could define another operator to compose (getter, setter) lenses and the rest of the machinery would work either way.
It's also possible that you can't get the full generality of (forall f. (s -> f t) -> a -> f b) lenses with getter/setter pairs, although I haven't worked through the details yet so don't know either way.
So, my question is: what is the advantage of representing lenses in the way that they are?
Many thanks,
David _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

On 27 January 2015 at 17:23, Charles Durham
You need to sign up for it, but this is a phenomenal talk by simon peyton jones describing the idea behind lenses the way he understood it.
https://skillsmatter.com/skillscasts/4251-lenses-compositional-data-access-a...
Thanks, I think that was exactly what I needed to know. If I understand the key section right, you can do all that stuff with a straight get/set pair but it'd be desperately inefficient, so then you add an update function, and then one at Maybe and [] and IO and they all start to look the same so you generalise to all Functors, and then you discover that using Const you get a getter, and Identity gives you a setter, so you can throw them away and end up with a lens as we know it. And then you generalise it in about a billion other directions and you end up with the lens library! Much obliged, David

On Tue, Jan 27, 2015 at 9:29 PM, David Turner
On 27 January 2015 at 17:23, Charles Durham
wrote: You need to sign up for it, but this is a phenomenal talk by simon peyton jones describing the idea behind lenses the way he understood it.
https://skillsmatter.com/skillscasts/4251-lenses-compositional-data-access-a...
Thanks, I think that was exactly what I needed to know.
If I understand the key section right, you can do all that stuff with a straight get/set pair but it'd be desperately inefficient, so then you add an update function, and then one at Maybe and [] and IO and they all start to look the same so you generalise to all Functors, and then you discover that using Const you get a getter, and Identity gives you a setter, so you can throw them away and end up with a lens as we know it.
And then you generalise it in about a billion other directions and you end up with the lens library!
Just wanted to note that 'lens' is not the only lens library. There are many others (data-lens, fclabels, data-accessor, ...) and most use a getter/setter or getter/modifier combination. Erik

glad that helped, definitely helped me
On Tue, Jan 27, 2015 at 3:29 PM, David Turner wrote: On 27 January 2015 at 17:23, Charles Durham You need to sign up for it, but this is a phenomenal talk by simon peyton
jones describing the idea behind lenses the way he understood it. https://skillsmatter.com/skillscasts/4251-lenses-compositional-data-access-a... Thanks, I think that was exactly what I needed to know. If I understand the key section right, you can do all that stuff with
a straight get/set pair but it'd be desperately inefficient, so then
you add an update function, and then one at Maybe and [] and IO and
they all start to look the same so you generalise to all Functors, and
then you discover that using Const you get a getter, and Identity
gives you a setter, so you can throw them away and end up with a lens
as we know it. And then you generalise it in about a billion other directions and you
end up with the lens library! Much obliged, David

On Tue, Jan 27, 2015 at 05:18:41PM +0000, David Turner wrote:
I believe that the types (a -> s, s -> a -> a) and (forall f. Functor f => (s -> f s) -> a -> f a) are isomorphic. Is that right?
Yes (with the caveat that I don't actually know how to prove this).
It's also possible that you can't get the full generality of (forall f. (s -> f t) -> a -> f b) lenses with getter/setter pairs
No, they are equivalent.
So, my question is: what is the advantage of representing lenses in the way that they are?
The advantage that's most obvious to me is polymorphism. You can use a lens forall f. Functor f => (s -> f s) -> a -> f a where the callee expects a traversal forall f. Applicative f => (s -> f s) -> a -> f a This is very convenient in practice. Perhaps there are other practical advantages that someone else can explain. Tom

For the record, I think the isomorphism uses the Const s functor to
recover the getter and the Identity functor to recover the setter.
It's something like this:
Given (get, set), the corresponding lens is \f x. fmap (flip set x) (f (get x))
Given a lens ell the getter/setter pair is (runConst . ell Const, \v
-> runIdentity . ell (Identity . const v))
Notice that Const s is not an Applicative (e.g. pure :: () -> Const
Void () doesn't exist) which is why (forall f. Applicative f => (s ->
f s) -> a -> f a) proscribes getting your hands on the getter.
On 27 January 2015 at 17:25, Tom Ellis
On Tue, Jan 27, 2015 at 05:18:41PM +0000, David Turner wrote:
I believe that the types (a -> s, s -> a -> a) and (forall f. Functor f => (s -> f s) -> a -> f a) are isomorphic. Is that right?
Yes (with the caveat that I don't actually know how to prove this).
It's also possible that you can't get the full generality of (forall f. (s -> f t) -> a -> f b) lenses with getter/setter pairs
No, they are equivalent.
So, my question is: what is the advantage of representing lenses in the way that they are?
The advantage that's most obvious to me is polymorphism. You can use a lens
forall f. Functor f => (s -> f s) -> a -> f a
where the callee expects a traversal
forall f. Applicative f => (s -> f s) -> a -> f a
This is very convenient in practice. Perhaps there are other practical advantages that someone else can explain.
Tom _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

On Tue, Jan 27, 2015 at 05:50:44PM +0000, David Turner wrote:
Notice that Const s is not an Applicative (e.g. pure :: () -> Const Void () doesn't exist) which is why (forall f. Applicative f => (s -> f s) -> a -> f a) proscribes getting your hands on the getter.
Right, unless `s` is a `Monoid` in which case you can "get" out of a `Traversal` by combining all the targets :)
participants (5)
-
Charles Durham
-
David Feuer
-
David Turner
-
Erik Hesselink
-
Tom Ellis