Author：Kenta Inoue

We introduce the Lens type, which is used for handling objects in functional programming, using the functional programming language Haskell.

First, we show the types of getter and setter, which are the features of object-oriented programming.

## Types of getter and setter

Let `s`

be the type of an object and `a`

be the
type of a variable, the getter function `get`

and the
setter function `set`

have the following types.

```
get :: s -> a
set :: s -> a -> s
```

However, `get`

and `set`

need to satisfy for
any object `s`

and input `a`

, `b`

.

```
get (set s a) = a
set s (get s) = s
set (set s b) a = set s a
```

The first is that getting after setting the value a in the object, should output the same value. The second is that setting the value obtained from get directly using set should result in an object equal to the original one. The third is that repeating multiple set operations is equivalent to applying only the last set.

## make getter and setter from Lens

While functions like `set`

and `get`

are
straightforward for handling objects, we can create a function of
type `MyLens`

by combining these two, as shown below.

```
type MyLens s a = forall f. Functor f => (a -> f a) -> s -> f s
```

In fact, the functions `get`

and `set`

can be
defined from `MyLens`

, and vice versa.

```
{- get & set -> lens -}
mkMyLens :: (s -> a) -> (s -> a -> s) -> MyLens s a
mkMyLens get set f s = set s <$> f (get s)
{- lens -> get -}
mkGet :: MyLens s a -> s -> a
mkGet lens = getConst . lens Const
{- lens -> set -}
mkSet :: MyLens s a -> s -> a -> s
mkSet lens s a = runIdentity $ lens (\_ -> Identity a) s
```

Furthermore, the following properties also hold for any
`get`

and `set`

.

```
mkGet (mkLens get set) s = get s
mkSet (mkLens get set) s a = set s a
```

In short, both `get`

and `set`

can be replaced
using a single `MyLens`

type.
However, `Lens`

type in Haskell is different from this
`MyLens`

.

# Lens in Haskell

In Haskell, we generally use `Lens`

type which is
generalized from the previous `MyLens`

type.

```
type Lens s t a b = forall f. Functor f => (a -> f b) -> s -> f t
```

In fact, `MyLens`

can be written from `Lens`

and is already defined in libraries named as `Lens'`

.

```
type MyLens s a = Lens s s a a
```

```
type Lens' s a = Lens s s a a
```

## the relation between getter, setter and Lens

The corresponding types for Getter and Setter for
this `Lens`

are:

```
Lens s t a b :: forall f. Functor f => (a -> f b) -> s -> f t
get :: s -> a
set :: s -> b -> t
```

Actually, `get`

and `set`

can also be defined
from `Lens`

, and vice versa.

```
{- get & set -> Lens -}
lens :: (s -> a) -> (s -> b -> t) -> Lens s t a b
lens sa sbt afb s = sbt s <$> afb (sa s)
{- Lens -> get -}
myView :: MonadReader s m => Lens s t a b -> m a
myView lens = Control.Monad.Reader.asks (getConst . lens Const)
myView' :: Lens s t a b -> s -> a
myView' = myView
{- view :: MonadReader s m => Getting a s a -> m a -}
{- type Getting r s a = (a -> Const r a) -> s -> Const r s -}
{- Lens -> set -}
set :: ASetter s t a b -> b -> s -> t
set l b = runIdentity . l (\_ -> Identity b)
mySet :: Lens s t a b -> s -> b -> t
mySet lens = flip $ set lens
{- type ASetter s t a b = (a -> Identity b) -> s -> Identity t -}
```

While `view`

is defined only on `Lens s s a a`

in the library, we can generalize it on `Lens s t a b`

as
`myView`

.

As with `MyLens`

, the following properties also hold for
any `get`

and `set`

.

```
myGet (lens get set) s = get s
mySet (lens get set) s a = set s a
```

# conclusion

The `Lens`

type is beneficial for representing objects in
functional programming languages.