There are variety of libraries offering lens on the hackage. These include data-accessor, fclabels, lenses, data-lens and lens. Though they represent the same idea, their encodings of lens are not compatible. This article is an attempt to understand various encodings used to represent the idea of lens.

# Lens as a getter and a setter

The most intuitive way to encode lens is to represent it as a collection of a *getter* and a *setter*. `Lens s a`

represents a *focus* to an `a`

inside an `s`

structure.

```
data Lens s a = Lens
{ get :: s -> a
, set :: a -> s -> s
}
```

We can define a lens to the first element of a pair as follows:

```
fstL :: Lens (a,b) a
fstL = Lens {
get = \(x,y) -> x
, set = \x (_,y) -> (x,y)
}
```

Similarly, we can define `snd`

:

```
sndL :: Lens (a,b) b
sndL = Lens {
get = \(x,y) -> y
, set = \y (x,_) -> (x,y)
}
```

Having defined this, it is easy to access and modify a pair:

```
> get fstL (1,2)
1
> set fstL 3 (1,2)
(3,2)
```

We can also implement `update`

in terms of `get`

and `set`

by getting the value, applying a function and setting it again.

```
update :: Lens s a -> (a -> a) -> s -> s
update l f s = set l (f (get l s)) s
```

This `update`

function works fine for a small data structure such as pairs, but becomes expensive for large data structures as it needs to visit all the way down to the *focus* twice every time it updates.

```
> update fstL (+1) (1,2)
(2,2)
```

Lenses are composable with `compose`

function:

```
compose :: Lens b c -> Lens a b -> Lens a c
compose bc ab = Lens
{ get = get bc . get ab
, set = update ab . set bc
}
```

We can now modify nested pairs:

```
> update (sndL `compose` fstL) (*2) ((3,4),5)
((3,8),5)
```

# Lens as a getter and an updater

A slight variation to the previous lens encoding is to represent a lens with a *getter* and an *updater* instead of a *getter* and a *setter*.

```
data Lens s a = Lens
{ get :: s -> a
, update :: (a -> a) -> s -> s
}
```

The performance of this encoding is better than the previous one because we no longer need to visit the *focus* twice for an single update. `fstL`

and `sndL`

directly implement `update`

as follows:

```
fstL :: Lens (a,b) a
fstL = Lens {
get = \(x,y) -> x
, update = \f (x,y) -> (f x,y)
}
sndL :: Lens (a,b) b
sndL = Lens {
get = \(x,y) -> y
, update = \f (x,y) -> (x, f y)
}
```

But what about `set`

? We can easily define `set`

in terms of `update`

using `const`

function:

```
set :: Lens s a -> a -> s -> s
set l a s = update l (const a) s
```

Composition of two lenses are similarly defined:

```
compose :: Lens b c -> Lens a b -> Lens a c
compose bc ab = Lens
{ get = get bc . get ab
, update = update ab . update bc
}
```

# CPS based lens (aka van Laarhoven lens)

This encoding is called *a CPS based lens* as the type looks like a continuation passing style function, which would be `(b -> r) -> (a -> r)`

though the return type is `f a`

instead of any `r`

. It is also called van Laarhoven lens named after **Twan van Laarhoven** who first discovered this encoding.

This is the most popular lens encoding as it is used by the famous Edward Kmett’s lens library.

```
{-# LANGUAGE Rank2Types #-}
type Lens s a = forall f. Functor f => (a -> f a) -> (s -> f s)
```

It is hard to understand the type at first sight. There are no longer identifiable setter or getter in the type signature. Instead, we have a functor `f`

in the signature.

As expected from the clue, we can derive `get`

and `update`

by applying different functors to the type.

First, we derive `get`

by applying `Const`

functor:

```
import Control.Applicative
get :: Lens s a -> s -> a
get l = getConst . l Const
```

Also we can derive `update`

by applying `Identity`

functor:

```
import Control.Monad.Identity
update :: Lens s a -> (a -> a) -> s -> s
update l m = runIdentity . l (Identity . m)
```

`set`

function can be implemented in terms of `get`

and `update`

as usual:

```
set :: Lens s a -> a -> s -> s
set l b a = update l (const b) a
```

Fortunately, defining a lens in var Laarhoven lens encoding is not hard. For example, we can define `fstL`

using `fmap`

:

```
fstL :: Lens (a,b) a
fstL f (x,y) = fmap (\a -> (a, y)) (f x)
```

Or we can define `sndL`

more succinctly using `TupleSections`

and `(<$>)`

operator:

```
sndL :: Lens (a,b) b
sndL x (a,b) = (a,) <$> x b
```

As this job of defining a lens is so mechanical, lens library provides a TemplateHaskell macro to generate lenses from a record.

Let’s see how `get`

works by actually evaluating `get fstL (1,2)`

:

```
get fstL (1,2)
=> getConst . (fstL Const) (1,2)
=> getConst . (\x (a,b) -> (,b) <$> x a) (1,2)
=> getConst . (\(a,b) -> (,b) <$> Const a) (1,2)
=> getConst . ((,2) <$> Const 1)
=> getConst . (Const 1)
=> 1
```

One particularly nice property of var Laarhoven lens is that composition of two lens is just the function composition operator `(.)`

.

```
compose :: Lens b c -> Lens a b -> Lens a c
compose r s = s . r
```

So we can simply use the `(.)`

to compose two lenses instead of custom `compose`

function.

```
> update (fstL . sndL) (*2) ((3,4),5)
((3,8),5)
```

However, the order of composition is reversed due to the nature of CPS based encoding. This is a bit confusing at first, but it makes sense when we think of it as a property referencing in an OO language.

`pair.(fstL.sndL) *= 2`

This style of composition is also possible with previous two encodings if we use Haskell’s type classes to overload `(.)`

and `id`

as described in Overloading functional references. But van Laarhoven lens is still simpler as we don’t need to hide the `(.)`

operator of the `Prelude`

.

# Isomorphism lens

There is a yet another encoding of lens called Isomorphism lens which was also discovered by van Laarhoven.

A lens from type s to a is a bijection between s and a pair of a and some residual r.

To put it more succinctly,

`type Lens s a = exists r. s <-> (a,r)`

Because Haskell has no `exists`

keyword, we can represent the encoding with a `newtype`

wrapper:

```
{-# LANGUAGE Rank2Types #-}
{-# LANGUAGE ExistentialQuantification #-}
-- Isomorphisms/bijections between type @a@ and @b@
data Iso a b = Iso { fw :: a -> b, bw :: b -> a }
-- Lenses with a data wrapper, in practice you might want to unpack the Iso type
data Lens s a = forall r. Lens (Iso s (a,r))
```

This encoding captures the intuition of what lens does extremely well. Suppose we have a record type `s`

, and want to take out a field of type `a`

. When we do that, there is some residual, which is `s - a`

. So `s`

and `(a, s - a)`

is must be isomorphic.

We can define `get`

and `update`

as follows:

```
import Data.Bifunctor
get :: Lens s a -> s -> a
get (Lens l) = fst . fw l
update :: Lens s a -> (a -> a) -> (s -> s)
update (Lens l) f = bw l . first f . fw l
```

`set`

function is the same as before:

```
set :: Lens s a -> a -> s -> s
set l b a = update l (const b) a
```

Isomorphism lens has the nice property that we can derive lens laws directly from the isomorphism law.

fw i . bw i = bw i . fw i = id

See van Laarhoven’s article to see how we can derive three lens law.