# Let's learn about lenses

Posted on August 21, 2018

Before we begin: in order to understand a lot of the following you’ll first need some familiarity with Haskell syntax and be somewhat comfortable with what a Functor is.

OK, now firstly: why learn about lenses? Every time I’ve seen lenses in action it’s looked like wizardry. I mean, just look at these examples of using `lens-aeson`

:

```
someJson =
[json| {
packages: [
{ version: 1 },
{ version: 5 }
]
}|]
versions =
key "packages"
. _Array
. traverse
. key "version"
. _Number
print $ someJson ^.. versions
-- [1.0,5.0]
BS.putStrLn $ someJson & versions %~ (+ 2)
-- {
-- "packages": [
-- { "version": 3 },
-- { "version": 7 }
-- ]
-- }
```

*What?* Reaching into some JSON, transforming it and just putting it back together, there’s no way it can be so easy? Right?

Let’s try to understand what’s going on here. We should probably start with something a little simpler than the JSON example above, how about tuples?

OK, imagine we have these two magic functions. `_1`

for doing *stuff* to the first element of a tuple and `_2`

for doing *stuff* to the second.

We can compose them `_1 . _ 2`

, which lets us do *stuff* to the second element of a tuple which is itself the first element of a tuple.

What kind of stuff?

We can “view” (`^.`

) the value:

We can “modify” (`%~`

) the value:

We can traverse over a list of these tuples and view the value of each as a list (`^..`

with `traverse`

):

While we traverse (this time over any Traversable thing), instead of viewing we can modify:

```
> [((2, True), 'b'), ((3, False), 'b')] & traverse . _1 . _2 %~ not
[((2,False),'b'),((3,True),'b')]
```

That looks pretty useful to me. What do you reckon?

To understand how this all works we should probably move step by step. Let’s try this:

- First we’re going to define
*slightly*simplified versions of`_1`

and`_2`

, as`one`

and`two`

. - Then we’ll move on to define similarly simplified versions of
`^.`

(as`view`

) and`%~`

(as`modify`

). - Finally we’ll adapt
`_1`

and`_2`

to be a little closer to their definitions in the`lens`

library.

We might seek to explore `^..`

and how it interacts with `traverse`

in another post. It’s super cool, but we’ll likely need to get there via some other concepts.

## Lenses `_1`

(one) and `_2`

(two)

What are these two magic functions? How do they work?

We’ll start by describing “functional references” al la Twan van Laarhoven, a precursor to what we now call lenses. For the sake of simplicity we’re still going to refer to these as “lenses”.

In the above article a lens is defined as something with this type:

Let’s make an alias for use later.

The goal of this section is going to be implementing functions that satisfy this type. In the next section we’ll seek to understand *why* this type is the way it is.

Imagine that `s`

stands for “structure”, this will become clearer a little later.

Something bothered me when I first saw this type, it looks like it’s missing two functions: `s -> a`

, `a -> s`

. If we had an `s -> a`

we could turn the `s`

we get as a second argument into the `a`

we need to supply to the `a -> f a`

we receive as the first argument. If we had an `a -> s`

we could use `fmap`

to transform the `f a`

to an `f s`

ready to return it.

We could write a function which accepts an `s -> a`

and an `a -> s`

in order to build a lens, something like this:

```
makeLens
:: (s -> a)
-> (a -> s)
-> Lens' s a
makeLens sToA aToS aToFa s =
fmap aToS (aToFa (sToA s))
```

It ends up those functions are *precisely* what we need to provide to make a lens. The first function is the “getter”, the second the “setter”.

What might a getter for the first element of a tuple look like?

Looks about right. How about the setter?

That should work.

We don’t really *need* this `makeLens`

function, so let’s get rid of it.

We now do the getting by pattern matching and the setting with an anonymous function: `\a' -> (a', c)`

. We don’t need separate functions *necessarily* for getting and setting, which might explain why they’re not mentioned in the type.

Let’s compare the type of `one`

to the lens type above.

So `s`

in the lens type is `(a, c)`

in the type for `one`

. The getter function `s -> a`

is generic enough to say that “`a`

is some part of `s`

”, without being specific about what `s`

is at all.

OK, now `two`

is going to be pretty much the same, except that we’ll focus on the second element of the tuple.

If we compare it with the lens type:

All together now:

```
Functor f => (a -> f a) -> s -> f s
one :: Functor f => (a -> f a) -> (a, c) -> f (a, c)
two :: Functor f => (a -> f a) -> (c, a) -> f (c, a)
```

I reckon we’ve got a reasonable idea now how the functions `one`

and `two`

are lenses. That is to say: we can see how the types line up.

The next step is to understand how we can use each of these functions as both a getter and a setter.

## Lens interpreters `(^.)`

(view) and `(%~)`

(modify)

We’ve made the types line up, but to what end? What is this crazy type up to anyway? The genius here lies largely in the `Functor f`

constraint.

To start with we’ll pick a very boring Functor to stand in for `f`

: `Identity`

.

```
newtype Identity a = Identity { runIdentity :: a }
instance Functor Identity where
fmap :: (a -> b) -> Identity a -> Identity b
fmap f (Identity a) = Identity (f a)
```

See how boring this thing is? It’s just a container for a single value, all `fmap`

can do is unpack it to get at the `a`

inside, apply `f`

to `a`

and pack it back up again.

Note that our lenses expect a `a -> f a`

, which in this case will be `a -> Identity a`

. We have a function already which can fulfil that type, `Identity`

’s only data constructor:

So we can pass the `Identity`

data constructor as the first argument to `one`

and see what we get.

Hmm, and if we pass it some value?

Makes sense, and I guess all we can do now is unpack it using `runIdentity :: Identity a -> a`

:

Wait, this looks familiar.

Right, right. Cool. So absolutely nothing happens but in a fairly involved way.

We *can* make something happen though.

We can compose `Identity :: a -> Identity a`

with some `a -> a`

. We can write a pretty general function for this:

… an even *more* general function:

```
> modify lens modification value = runIdentity (lens (Identity . modification) value)
> modify one (+ 2) (1, 'a')
(3,'a')
```

Wow, what’s the type of `modify`

then?

Modify takes a lens:

An `a -> a`

, which will be composed with `Identity :: a -> Identity a`

, still giving us the `a -> Identity a`

we need:

And some value the lens can act on:

If we make things less generic for a second it might be a bit clearer:

```
one :: (a -> Identity a) -> (a, c) -> Identity (a, c)
one aToFa (a, c) = fmap (\a' -> (a', c)) (aToFa a)
-- ^^^^^ ^^^^^^^^^^^^^^^^^^^^^
-- | All this does is put the
-- | modified a back in the tuple:
-- | Identity a -> Identity (a, c)
-- |
-- |
-- This is the Identity data constructor composed
-- with some function a -> a, the modification
```

This is all pretty interesting but still doesn’t answer why we have the `Functor f`

constraint, `Identity`

here just makes getting to the value kinda obscure.

Let’s put another weird Functor in place of `f`

: `Const`

.

```
newtype Const c a = Const { getConst :: c }
instance Functor (Const c) where
fmap :: (a -> b) -> Const c a -> Const c b
fmap _ (Const c) = Const c
```

This was pretty mind-bending for me at first. What possible use could this thing have? It looks like it’s a Functor where `fmap`

doesn’t *do* anything, the function argument is totally ignored.

It’s worth having another look at the signature for `fmap`

in that last code block. The function argument isn’t applied, but the type *does* change. We’ve still gone from `f a`

to `f b`

after we’ve `fmap`

ed.

Let’s look at these `fmap`

s side by side.

```
fmap :: (a -> b) -> f a -> f b
fmap :: (a -> b) -> Identity a -> Identity b
fmap :: (a -> b) -> Const c a -> Const c b
```

What happens when we use `Const :: a -> Const a a`

as our `a -> f a`

in `one`

?

Huh? Weird. Wonder what the type is.

Right, so we *do* have a `Const a (a, c)`

, which fits the `f (a, c)`

returned by `one`

. The really interesting thing is that the “setter” part of `one`

didn’t actually get applied. `Const`

’s `fmap`

ignores that function argument.

```
one :: Functor f => (a -> f a) -> (a, c) -> f (a, c)
one aToFa (a, c) = fmap (\a' -> (a', c)) (aToFa a)
-- ^^^^^^^^^^^^^^^^
-- This is never run
```

Once more, if we make things less generic for a second it might be a bit clearer:

```
one :: (a -> Const a a) -> (a, c) -> Const a (a, c)
one aToFa (a, c) = fmap (\a' -> (a', c)) (aToFa a)
-- ^^^^^ ^^^^^^^^^^^^^^^^^^^^^
-- | All this does is
-- | change the type:
-- | Const a a -> Const a (a, c)
-- |
-- |
-- This is the Const data constructor.
```

The Functor constraint is satisfied, so we’re able to use `Identity`

and `Const`

interchangeably. When we use `Identity`

the setter function is run and so the updated value is popped back into our tuple, when we use `Const`

the setter is skipped.

Once again there’s little more we can do than unwrap the Functor:

Also once again, we can write a very generic version of this:

```
> view lens value = getConst (lens Const value)
> :t view
view :: ((a -> Const a a) -> s -> Const a s) -> s -> a
> view one (1, 'a')
1
```

## Polymorphism?

So far `modify`

is somewhat limited, we can only provide it functions that accept and return values of the same type (`a -> a`

). What might it take to adapt `one`

, `two`

and `modify`

to work with functions that accept one type and return another?

The answer is: nothing. All we need to do is change some type signatures and variable names. The actual functions are already good to go.

Our current lens type becomes the same as the lens library type by adding two more type variables: `b`

and `t`

. When we allow the value yanked out of `s`

to have it’s type changed from `a`

to `b`

, putting it back must be allowed to change the type of `s`

, and so we return `f t`

.

We can define another handy alias.

`one`

becomes `_1`

with only some type and value variable renaming:

```
one :: Lens' (a, c) a
one aToFa (a, c) =
fmap (\a' -> (a', c)) (aToFa a)
_1 :: Lens (a, c) (b, c) a b
_1 aToFb (a, c) =
fmap (\b -> (b, c)) (aToFb a)
```

As with `two`

to `_2`

:

```
two :: Lens' (c, a) a
two aToFa (c, a) =
fmap (\a' -> (c, a')) (aToFa a)
_2 :: Lens (c, a) (c, b) a b
_2 aToFb (c, a) =
fmap (\b -> (c, b)) (aToFb a)
```

`modify`

becomes `%~`

thusly

```
modify :: Lens' s a -> (a -> a) -> s -> s
modify lens modification value =
runIdentity $
lens (Identity . modification) value
(%~) :: Lens s t a b -> (a -> b) -> s -> t
(%~) lens modification value =
runIdentity $
lens (Identity . modification) value
infixr 7 %~
```

`view`

gets much the same treatment, we also flip the args to make it match `^.`

:

```
view :: Lens' s a -> s -> a
view lens value = getConst (lens Const value)
(^.) :: s -> Lens s t a b -> a
(^.) value lens = getConst (lens Const value)
infixr 7 ^.
```

And hey presto we have polymorphic lenses, quite like those in `Control.Lens`

!

Some more fun examples to see what we’ve done in action:

```
> ('a', 4) & _1 %~ (: "bc")
("abc",4)
> ('a', 4) & _2 %~ show
('a',"4")
> ('a', 4) ^. _1
'a'
> ('a', 4) ^. _2
4
-- Let's get crazy
> ('a', 4) & _1 %~ (: "bc") & _2 %~ (show . subtract 4)
("abc","0")
```

## Conclusion

This type didn’t make a heap of sense to me when I first saw it:

After having gone through all of the implementations above, I reckon I get it now. This is not to say I understand all the weird and wonderful things in lens, but I feel like I’m on the way. With any luck this may have helped you too.

Further reading:

The lens wiki has this awesome page full of links that really helped me with the above.

Most of the code samples from this article can be found in this gist