
Lenses: Composable Getters and Setters for Functional Programming - ericelliott
https://medium.com/javascript-scene/lenses-b85976cb0534
======
kccqzy
I love lenses and other optics like prisms and folds, but only in a statically
typed language like Haskell. It seems to me that it would be very hard to get
things right in a dynamically typed language:

* First, it's possible that different elements of an array or different properties of an object has different shapes. I can't imagine how lenses can deal with that in an idiomatic way.

* Second, it's just difficult to get things right without a compiler's help. Forget a `traverse`? Now you are operating nonsense on the wrong level of your nested data structure. Trying to modify an inner structure but you only have a Fold instead of a Traversal? You won't know it won't work without running it to get some cryptic error.

* Furthermore, without types, we obscure the fact that setters and getters are unified: if `a` stands for the part and `s` for the whole, we just have
    
    
        (a -> f a) -> (s -> f s)
    

that is, given a way to transform some inner part, we can transform the whole
as well. Getters and setters are just supplying a concrete choice of f, namely
the const functor and the identity functor. If we pick f to be the identity
functor, then with some unwrapping we have

    
    
        (a -> a) -> (s -> s)
    

so if there is a function that can modify the part, we have a function that
can modify the whole by keeping the rest the same and modify that part. If we
pick f to be the const functor, then with some unwrapping we have

    
    
        (a -> r) -> (s -> r)
    

so if there is a function that can extract the value from the part, we can
extract the value from the whole as well. Without types, this rather elegant
unification of getter and setter seems to be lost.

~~~
lilactown
Everything you said has nothing to do with lenses and everything to do with
trying to satisfy some statically-typed aesthetics.

> First, it's possible that different elements of an array or different
> properties of an object has different shapes

I can't imagine how this would introduce any sort of difficulties w.r.t.
lenses that aren't already present with normal getting and setting of nested
structures (aka probably not much).

> Second, it's just difficult to get things right without a compiler's help

This has nothing to do with lenses and everything to do with you preferring
the feel of static types. You go on to talk about a bunch of issues with
complex constructs that really only exist in static typing.

Sometimes you write a wrong thing and get a runtime error. This happens in all
dynamically typed languages (and many statically typed as well).

> Furthermore, without types... this rather elegant unification of getter and
> setter seems to be lost.

Like ya do. I don't see how this has any impact at all on developing
applications.

------
lindig
In a language like C, the dot '.' and the arrow '->' are used for access into
structures - both for setting and retrieving values. I think intuitively about
a lens as a programmable dot which I can use to compose an access path. (You
might have heard that the bind operator in a monad can be thought of as a
programmable semicolon - this is similar.) This intuition might mean little if
you haven't looked at lenses in more detail, but it does make sense once you
have.

~~~
mannykannot
Though these operators can be used in modifiable lvalue expressions, while
lenses are (according to this article) pure functions.

~~~
lindig
As pointed out in this thread, a lens has to return the modified object as it
can't update it as a side effect. That is the reason no universal dot-like
lens operator exists in Haskell but it needs to be composed based on the data
structures that it targets.

~~~
mannykannot
Well, yes, but bear in mind that the absence of side effects is seen as a
virtue in functional programming, and it is a point of view that I have
considerable agreement with.

------
nobleach
I recommend this post as well: [https://medium.com/@gcanti/introduction-to-
optics-lenses-and...](https://medium.com/@gcanti/introduction-to-optics-
lenses-and-prisms-3230e73bfcfe)

The author of the post is also the author of a TypeScript port of Monocle for
Scala.

------
coldcode
Has anyone done a performance analysis on the use of the lens concept in
various languages? Given it is essentially duplicating data for every set it
would seem to produce a lot of garbage for whatever memory allocator style is
in use.

~~~
aeneasmackenzie
In haskell they're optimized out, but some delicate work has gone into
ensuring that. They're actually faster than alternative methods in some cases,
uniplate was rewritten in lenses and got faster and with better type safety as
well.

------
renox
In C you don't need lens, either you set a member of a struct or you copy the
struct and you set a member of the copy, trivial stuff. Why do you need a
library for this kind of thing in Haskell?

~~~
marcosdumay
Is there a common idiom in C++ to deep copy a multi-level structure so you can
then change a field? In C I know there isn't, and you can not create a generic
function for it either.

How do you pass a member identification as a parameter to a function that may
receive any kind of structure, and then update that member?

Haskell has record accessors too, that are more equivalent to the C
functionality. Lenses are a different thing.

~~~
atilaneves
> How do you pass a member identification as a parameter to a function that
> may receive any kind of structure, and then update that member?

You don't. You just update that member.

~~~
marcosdumay
So, no generics available (templates are an option, but way to troublesome to
use for that). That aligns with my experience, but mine is currently out of
date, thus the question.

~~~
atilaneves
The main takeaway is that this isn't necessary with mutable structures. Nobody
would think of even trying to write a generic solution to a problem that
doesn't exist in C++.

~~~
marcosdumay
Lens are about composition and abstracting your operations over unknown
structures. I don't know where did you find anything about immutability, as
plain data accessors are perfectly fine for that.

The motivation on the article is basically this paragraph:

"Lenses allow you to abstract state shape behind getters and setters. Instead
of littering your codebase with code that dives deep into the shape of a
particular object, import a lens. If you later need to change the state shape,
you can do so in the lens, and none of the code that depends on the lens will
need to change."

Immutability does not make its way there.

------
jimbo1qaz
`set(lens, b, set(lens, store, a)) ≡ set(lens, b, store)`

Somehow i sense this code has arguments in the wrong order.

