This is why I don't get invited to many places.
Source: I've done a lot of Mondrian research while creating a board game where you actually make art in the Mondrian style while playing.
On a different note, I'd love to see that board game.
Looking at this and seeing "lens" and "prisms" is at once both familiar and extremely odd. These Mondrian shapes are just like my recursive tree maps. Familiar. But the concept of lens and prism is not at all how I thought of them as I was repeatedly generating them.
It was interesting to look at what I was doing from a more formal perspective. Thanks! Yet at the same time I wish I could understand a practical use for this. How would it make things any better in my visual representation to use these concepts?
Personally, I find the whole idea of presenting a visual representation of masses of data interesting. There was a challenge a while back about how to represent the entire catalog of ISBN for example:
This is particularly useful for providing copy-on-write semantics for immutable data structures. E.g. Putting a ring on a finger creates a new finger, which creates a new hand, which creates a new arm, which creates a new body. Using an appropriate lens, such updates become much simpler to write.
People often think of optics as only "OOP accessors but for FP" but they are strictly more powerful than OOP accessors.
let x = (set `bar.quux` new_quux) y
instead of let x = { foo: y.foo, bar: {baz: y.bar.baz, quux: new_quux} }
If the language allows, both expressions could be fully type-checked at compile time.In the end, all an iterator is is a thing that returns the next value.
In the end, all a functor is is a thing that takes a value of type A and returns a value of type B.
In the end, all a reader is is a thing that yields up some bytes (or other locally appropriate type) when .Read is called.
What makes them interesting is what you can build on them and how they can compose together. None of these concepts are all that interesting on their own. Like everything else I mention above, the primary utility of lenses is that it turns an MxN problem, where you need to implement all combinations of both sides of the functionality, into an M+N problem, where you implement N combinations of things that implement the interface and you can have M users that can use that generic interface.
However, if you are not a functional programmer this will seem particularly useless to you. People often claim monads are functional programming's response to mutability, but this merely one of the many misunderstandings of the concept, that just because one particular solution to mutability uses a monadic interface then that must be the purpose of the monadic interface. Lenses are probably a much better fit for the position of "functional programming's answer to mutability". But even in FP's you only really need them if you're dealing with deeply nested structures a lot, and especially if you want to deal with those deeply nested structures polymorphically. If you don't have that problem, even in FP you probably won't reach for lenses as regular record updates can get you a long way. Records can be seen as de facto lenses that go one layer down into the relevant type automatically, and if that's all you need then you'll never need the lens library.
Thus, if you are used to mutable programming, lenses are going to seem particularly useless to you. What's the point of taking something that's nearly useless and then composing multiple of them together, when the resulting composition is also nearly useless? The real utility in lenses is their packaging up of a Setter; the Getter is pretty easy to deal with with just a normal closure. So if you don't need Setters because you're used to just mutating things in a conventional imperative language, then there's nothing there for you.
This is why you see lots of attempts to port monads into imperative languages with varying degrees of accuracy and utility into conventional languages and have probably never seen anyone try to port lenses into them.
If you are a functional programmer, then I would reiterate that comment about nested structures. I think one of the most popular uses of lenses in the Haskell community is for dealing with JSON, when you need to just deal with it directly for whatever reason and can't easily turn it into typed values because the JSON format in question is too chaotic. That's a bad JSON format and one should never from any language spec out such a thing but if you're forced to deal with someone else's chaos you have no choice.
The point of the article was to try to explain them in simple terms through a graphical notation, so that they become more accessible and manageable by more people.