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" <ratzes@gmail.com> 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 < 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 <dct25-561bs@mythic-beasts.com> wrote:
Thanks, I'll give that a watch.
On 27 Jan 2015 17:23, "Charles Durham" <ratzes@gmail.com> 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 <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
_______________________________________________ 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 <ratzes@gmail.com> 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! Much obliged, David
On Tue, Jan 27, 2015 at 9:29 PM, David Turner <dct25-561bs@mythic-beasts.com> wrote:
On 27 January 2015 at 17:23, Charles Durham <ratzes@gmail.com> 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 <dct25-561bs@mythic-beasts.com
wrote:
On 27 January 2015 at 17:23, Charles Durham <ratzes@gmail.com> 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!
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 <tom-lists-haskell-cafe-2013@jaguarpaw.co.uk> wrote:
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