Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
The Mondrian introduction to functional optics (marcosh.github.io)
74 points by marcosh 11 hours ago | hide | past | favorite | 20 comments




Authenticity nitpick: during this period where Mondrian produced geometrical works, he was emerging from theosophy as a primary influence towards universal truths. A key part of this was never using green. It's my pet peeve when people cite Mondrian based on geometry and then use green.

This is why I don't get invited to many places.


Also, his abstract art was a push back against the realism in art at the time plus the horrible realism of war. He family said, "Abstract art is not the creation of another reality but the true vision of reality". He believed that by abstracting forms and colors to their essential horizontal and vertical lines and primary hues, an artist could express the fundamental, spiritual truths of the universe and achieve a pure, universal beauty and dynamic equilibrium.

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.


Fascinating vision about abstract art. And here I thought all these artists were trying to get away from reality.

On a different note, I'd love to see that board game.


Man I'd like to hang out. No one I know is a Mondrian nerd. I love all his work and have a few replicas hanging around my home.

My grandfather was a painter. He had a friend who shared a studio with Mondrian at one point. His friend said that Mondrian would be very quiet then periodically would shout along the lines of "FUCK NOW I NEED TO MOVE THIS LINE HALF AN INCH TO THE LEFT."

Recently I went down the rabbit hole of recursive tree maps. Walk a file system directory and assign a weight (size) to each directory recursively. Then present a tree map of each level. Click on "Users" then "fred", then "clones" for example.

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:

https://news.ycombinator.com/item?id=43168838


This has nothing to do with physical optics if I understood it right? The blog post does use concepts such as lens and prism so I'm a bit confused.

Category theorists seem to enjoy coming up with confusing nomenclature.

compared to CS nomenclature which is all crystal clear

Correct. The term "optics" is used by analogy; functional optics let us "zoom in" on parts of a data structure, and "zoom out to" a data structure surrounding a value.

The name lens came from the property of their letting you "focus" onto parts of a larger data structure. The prism nomenclature is more tenuous - prisms evoke the imagery of a beam of light splitting into its constituent parts, and with a prism you can see a particular facet of the whole (sum types).

This has to do with category theory and programming notions of optics and lenses.

It is a fantastic explanation of the concept on its own, as a mathematical object, but I still struggle to understand its value as a practical primitive in programming.

Practically speaking, optics are useful for avoiding long chains of nested field access, like myBody.LeftArm.Hand.RingFinger.

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.


I agree that "concisely updating immutable data structures" is the easiest way to show how this is useful.

  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.

But also things like myBody.BothArms.Hand.RingFinger which targets the ring fingers on both hands at the same time, or myBody.LeftArm.Hand.RingFinger.WeddingBand which targets a ring that might not exist, or myBody.LeftArm.Hand.RingFinger.Straight which targets the ring finger when it is stretched out straight.

People often think of optics as only "OOP accessors but for FP" but they are strictly more powerful than OOP accessors.


In the end, all an optic is is a tuple of (Getter, Setter), where in a pure functional context the Setter returns a new value.

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.


This is a great way to present the concepts. Something like this would have been useful some years back when I was trying to use the Haskell library for lens.


Maybe it’s too early in the morning but - I don’t get it. Is the point of this artistic? Just for fun? Or is this useful somehow? What does visually representing types and values as ‘optics’ that can be sliced vertically and horizontally ‘do’ for us?



Consider applying for YC's Winter 2026 batch! Applications are open till Nov 10

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

Search: