Lenses have been on my mind since encountering them last year in the context of Haskell. Much of the literature on lenses has a very Haskell slant so show how they can be used in OCaml.
The theory of lenses and their accompanying prisms and traversals, have been better described by other people. This article at FPComplete was a particularly good one. I’m just going to cover how to use ocaml-lens as a minimal lens implementation.
First since ocaml-lens isn’t in opam, clone the repo locally and open up
utop. Then load the
lens.ml file into
Starting with a few record types for a car, editor and book.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
Creating a new book is as simple as.
1 2 3 4 5 6 7 8 9 10 11 12 13
scifi_novel we can access the editor’s car mileage:
Setting the mileage is a bit trickier, we need to unpack each record:
1 2 3
That’s not really an appealing prospect, can we do better?
Enter lenses, at the most simple level a lense is a pair of functions for getting and setting a property.
1 2 3 4 5 6 7
With this definition of a lens, modifying the mileage is now:
In the background we need to define some lenses for the records above:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Using these definitions the original lens version of modify the editor’s car mileage works.
The compose operator we used allows us to combine 2 lenses to go from the novel into the editor and then into the car. And compose can be combined with itself to build up arbitarily deep lenses into a structure.
This way of composing can seem backwards, you supply the inner lens first then
the outer lens. We can fix that by using the infix operators, open the
module and define the same lens:
This feels more intuative reading it left to right. Revisiting our original
_set mileage example we can now write it.
1 2 3
The infix module comes with some other helpful operators like
|. for get and
^= for set. All these operators avoid mutation so our
code remains pure and referentially transparent.
There are a heap more things that lenses can do, and while this ocaml-lens
package is pretty basic, looking at the hundreds of functions exported by
in Haskell you can get a good idea of the possibilities.
all the basic lens functions plus things like:
prismswhich are lenses but for sum types
traversalsare lenses that focus on multiple targets simultaneously
I made use of the following resources to write this and took some of the examples and definitions from the following articles. All mistakes are my own and probably accidental.