# Haskell/Solutions/Lenses and functional references

← Back to Lenses and functional references

## The scenic route to lenses[edit | edit source]

### Traversals[edit | edit source]

1.

```
extremityCoordinates :: Applicative f
=> (Double -> f Double) -> Segment -> f Segment
extremityCoordinates g (Segment start end) =
Segment <$> pointCoordinates g start <*> pointCoordinates g end
```

### Setters[edit | edit source]

1.

```
scaleSegment :: Double -> Segment -> Segment
scaleSegment x = over extremityCoordinates (x *)
```

2.

```
mapped :: Functor f => (a -> Identity b) -> f a -> Identity (f b)
mapped f = Identity . fmap (runIdentity . f)
```

### Lenses at last[edit | edit source]

1.

```
positionX :: Functor f => (Double -> f Double) -> Point -> f Point
positionX k p = (\x -> p { _positionX = x }) <$> k (_positionX p)
positionY :: Functor f => (Double -> f Double) -> Point -> f Point
positionY k p = (\y -> p { _positionY = y }) <$> k (_positionY p)
segmentStart :: Functor f => (Point -> f Point) -> Segment -> f Segment
segmentStart k s = (\p -> s { _segmentStart = p }) <$> k (_segmentStart s)
segmentEnd :: Functor f => (Point -> f Point) -> Segment -> f Segment
segmentEnd k s = (\p -> s { _segmentEnd = p }) <$> k (_segmentEnd s)
```

2.

```
lens :: Functor f => (s -> a) -> (s -> b -> t)
-> (a -> f b) -> s -> f t
lens getter setter = \k x -> setter x <$> k (getter x)
```

## A swiss army knife[edit | edit source]

### Prisms[edit | edit source]

1a.

The challenge lies in decoding the type of `outside`

:

```
outside :: Prism s t a b
-> Lens (t -> r) (s -> r) (b -> r) (a -> r)
```

It is easier to get a general idea of what is going on if we specialise it to prisms that do not change types.

```
Prism' s a -> Lens' (s -> r) (a -> r)
```

Given a `Prism'`

that aims at a possible target of type `a`

within an `s`

, `outside`

gives us a `Lens'`

that aims at a `a -> r`

function *within* a `s -> r`

function. If we go back to the original type, which allows type-changing prisms, we note that the `s`

/`t`

and `a`

/`b`

pairs are swapped. That happens because the type variables of the prism appear in the arguments of the functions the lens deals with. We might say that `outside`

is contravariant, in a similar sense to the one we used when discussing contarvariant functors earlier in the chapter.

There is something very odd in what we just said that requires further explanation. What can possibly mean saying that a function is within another function? To answer that, let's have a look at the type of `either`

:

```
either :: (a -> c) -> (b -> c) -> Either a b -> c
either f _ (Left x) = f x
either _ g (Right y) = g y
```

`either`

extracts a value from an `Either a b`

value. To do so, it relies on two functions: a `a -> c`

one that handles values wrapped by `Left`

and a `b -> c`

one to handle `Right`

. `either f g`

is then a `Either a b -> c`

that can be seen as being made of two components, `f`

and `g`

, each of them handling one of `Either`

's constructors. These function components are what `outside`

modifies. It is in that sense that `outside`

uses a prism as a "first-class pattern". Any `Either a b -> c`

function is necessarily doing pattern matching, deconstructing an `Either a b`

to produce its `c`

result. `outside _Left`

and `outside _Right`

allow us to modify the way such a function handles each pattern.

1b.

```
maybe :: b -> (a -> b) -> Maybe a -> b
maybe xNothing fJust
= outside _Just .~ fJust
$ const xNothing -- A default Maybe a -> b function.
either :: (a -> c) -> (b -> c) -> Either a b -> c
either fLeft fRight
= outside _Left .~ fLeft
$ outside _Right .~ fRight
$ error "Impossible" -- There is no sensible default here.
```