Darren Hester for openphoto.net

Today, let’s look at lenses. It’s a hot topic many people are talking, and looks like it has clear use case.

Seth Tisue (@SethTisue) gave a talk on shapeless lenses at Scalathon this year. I missed the talk, but I am going to borrow his example.

```
scala> case class Point(x: Double, y: Double)
defined class Point
scala> case class Color(r: Byte, g: Byte, b: Byte)
defined class Color
scala> case class Turtle(
position: Point,
heading: Double,
color: Color)
scala> Turtle(Point(2.0, 3.0), 0.0,
Color(255.toByte, 255.toByte, 255.toByte))
res0: Turtle = Turtle(Point(2.0,3.0),0.0,Color(-1,-1,-1))
```

Now without breaking the immutability, we want to move the turtle forward.

```
scala> case class Turtle(position: Point, heading: Double, color: Color) {
def forward(dist: Double): Turtle =
copy(position =
position.copy(
x = position.x + dist * math.cos(heading),
y = position.y + dist * math.sin(heading)
))
}
defined class Turtle
scala> Turtle(Point(2.0, 3.0), 0.0,
Color(255.toByte, 255.toByte, 255.toByte))
res10: Turtle = Turtle(Point(2.0,3.0),0.0,Color(-1,-1,-1))
scala> res10.forward(10)
res11: Turtle = Turtle(Point(12.0,3.0),0.0,Color(-1,-1,-1))
```

To update the child data structure, we need to nest `copy`

call. To quote from Seth’s example again:

```
// imperative
a.b.c.d.e += 1
// functional
a.copy(
b = a.b.copy(
c = a.b.c.copy(
d = a.b.c.d.copy(
e = a.b.c.d.e + 1
))))
```

The idea is to get rid of unnecessary `copy`

calls.

Let’s look at `Lens`

in Scalaz7:

```
type Lens[A, B] = LensT[Id, A, B]
object Lens extends LensTFunctions with LensTInstances {
def apply[A, B](r: A => Store[B, A]): Lens[A, B] =
lens(r)
}
```

`Lens`

is a type alias for `LensT[Id, A, B]`

like many other typeclasses.

`LensT`

looks like this:

```
import StoreT._
import Id._
sealed trait LensT[F[+_], A, B] {
def run(a: A): F[Store[B, A]]
def apply(a: A): F[Store[B, A]] = run(a)
...
}
object LensT extends LensTFunctions with LensTInstances {
def apply[F[+_], A, B](r: A => F[Store[B, A]]): LensT[F, A, B] =
lensT(r)
}
trait LensTFunctions {
import StoreT._
def lensT[F[+_], A, B](r: A => F[Store[B, A]]): LensT[F, A, B] = new LensT[F, A, B] {
def run(a: A): F[Store[B, A]] = r(a)
}
def lensgT[F[+_], A, B](set: A => F[B => A], get: A => F[B])(implicit M: Bind[F]): LensT[F, A, B] =
lensT(a => M(set(a), get(a))(Store(_, _)))
def lensg[A, B](set: A => B => A, get: A => B): Lens[A, B] =
lensgT[Id, A, B](set, get)
def lensu[A, B](set: (A, B) => A, get: A => B): Lens[A, B] =
lensg(set.curried, get)
...
}
```

What’s a `Store`

?

```
type Store[A, B] = StoreT[Id, A, B]
// flipped
type |-->[A, B] = Store[B, A]
object Store {
def apply[A, B](f: A => B, a: A): Store[A, B] = StoreT.store(a)(f)
}
```

It looks like a wrapper for setter `A => B => A`

and getter `A => B`

.

Let’s define `turtlePosition`

and `pointX`

:

```
scala> val turtlePosition = Lens.lensu[Turtle, Point] (
(a, value) => a.copy(position = value),
_.position
)
turtlePosition: scalaz.Lens[Turtle,Point] = scalaz.LensTFunctions$$anon$5@421dc8c8
scala> val pointX = Lens.lensu[Point, Double] (
(a, value) => a.copy(x = value),
_.x
)
pointX: scalaz.Lens[Point,Double] = scalaz.LensTFunctions$$anon$5@30d31cf9
```

Next we can take advantage of a bunch of operators introduced in `Lens`

. Similar to monadic function composition we saw in `Kleisli`

, `LensT`

implements `compose`

(symbolic alias `<=<`

), and `andThen`

(symbolic alias `>=>`

). I personally think `>=>`

looks cool, so let’s use that to define `turtleX`

:

```
scala> val turtleX = turtlePosition >=> pointX
turtleX: scalaz.LensT[scalaz.Id.Id,Turtle,Double] = scalaz.LensTFunctions$$anon$5@11b35365
```

The type makes sense since it’s going form `Turtle`

to `Double`

. Using `get`

method we can get the value:

```
scala> val t0 = Turtle(Point(2.0, 3.0), 0.0,
Color(255.toByte, 255.toByte, 255.toByte))
t0: Turtle = Turtle(Point(2.0,3.0),0.0,Color(-1,-1,-1))
scala> turtleX.get(t0)
res16: scalaz.Id.Id[Double] = 2.0
```

Success! Setting a new value using `set`

method should return a new `Turtle`

:

```
scala> turtleX.set(t0, 5.0)
res17: scalaz.Id.Id[Turtle] = Turtle(Point(5.0,3.0),0.0,Color(-1,-1,-1))
```

This works too. What if I want to `get`

the value, apply it to some function, and `set`

using the result? `mod`

does exactly that:

```
scala> turtleX.mod(_ + 1.0, t0)
res19: scalaz.Id.Id[Turtle] = Turtle(Point(3.0,3.0),0.0,Color(-1,-1,-1))
```

There’s a symbolic variation to `mod`

that’s curried called `=>=`

. This generates `Turtle => Turtle`

function:

```
scala> val incX = turtleX =>= {_ + 1.0}
incX: Turtle => scalaz.Id.Id[Turtle] = <function1>
scala> incX(t0)
res26: scalaz.Id.Id[Turtle] = Turtle(Point(3.0,3.0),0.0,Color(-1,-1,-1))
```

We are now describing change of internal values upfront and passing in the actual value at the end. Does this remind you of something?

That sounds like a state transition to me. In fact `Lens`

and `State`

I think are good match since they are sort of emulating imperative programming on top of immutable data structure. Here’s another way of writing `incX`

:

```
scala> val incX = for {
x <- turtleX %= {_ + 1.0}
} yield x
incX: scalaz.StateT[scalaz.Id.Id,Turtle,Double] = scalaz.StateT$$anon$7@38e61ffa
scala> incX(t0)
res28: (Turtle, Double) = (Turtle(Point(3.0,3.0),0.0,Color(-1,-1,-1)),3.0)
```

`%=`

method takes a function `Double => Double`

and returns a `State`

monad that expresses the change.

Let’s make `turtleHeading`

and `turtleY`

too:

```
scala> val turtleHeading = Lens.lensu[Turtle, Double] (
(a, value) => a.copy(heading = value),
_.heading
)
turtleHeading: scalaz.Lens[Turtle,Double] = scalaz.LensTFunctions$$anon$5@44fdec57
scala> val pointY = Lens.lensu[Point, Double] (
(a, value) => a.copy(y = value),
_.y
)
pointY: scalaz.Lens[Point,Double] = scalaz.LensTFunctions$$anon$5@ddede8c
scala> val turtleY = turtlePosition >=> pointY
```

This is no fun because it feels boilerplatey. But, we can now move turtle forward! Instead of general `%=`

, Scalaz even provides sugars like `+=`

for `Numeric`

lenses. Here’s what I mean:

```
scala> def forward(dist: Double) = for {
heading <- turtleHeading
x <- turtleX += dist * math.cos(heading)
y <- turtleY += dist * math.sin(heading)
} yield (x, y)
forward: (dist: Double)scalaz.StateT[scalaz.Id.Id,Turtle,(Double, Double)]
scala> forward(10.0)(t0)
res31: (Turtle, (Double, Double)) = (Turtle(Point(12.0,3.0),0.0,Color(-1,-1,-1)),(12.0,3.0))
scala> forward(10.0) exec (t0)
res32: scalaz.Id.Id[Turtle] = Turtle(Point(12.0,3.0),0.0,Color(-1,-1,-1))
```

Now we have implemented `forward`

function without using a single `copy(position = ...)`

. It’s nice but we still needed some prep work to get here, so there is some tradeoff. `Lens`

defines a lot more methods, but the above should be a good starter. Let’s see them all again:

```
sealed trait LensT[F[+_], A, B] {
def get(a: A)(implicit F: Functor[F]): F[B] =
F.map(run(a))(_.pos)
def set(a: A, b: B)(implicit F: Functor[F]): F[A] =
F.map(run(a))(_.put(b))
/** Modify the value viewed through the lens */
def mod(f: B => B, a: A)(implicit F: Functor[F]): F[A] = ...
def =>=(f: B => B)(implicit F: Functor[F]): A => F[A] =
mod(f, _)
/** Modify the portion of the state viewed through the lens and return its new value. */
def %=(f: B => B)(implicit F: Functor[F]): StateT[F, A, B] =
mods(f)
/** Lenses can be composed */
def compose[C](that: LensT[F, C, A])(implicit F: Bind[F]): LensT[F, C, B] = ...
/** alias for `compose` */
def <=<[C](that: LensT[F, C, A])(implicit F: Bind[F]): LensT[F, C, B] = compose(that)
def andThen[C](that: LensT[F, B, C])(implicit F: Bind[F]): LensT[F, A, C] =
that compose this
/** alias for `andThen` */
def >=>[C](that: LensT[F, B, C])(implicit F: Bind[F]): LensT[F, A, C] = andThen(that)
}
```

Seth says:

lens laws are common sense

(0. if I get twice, I get the same answer) 1. if I get, then set it back, nothing changes. 2. if I set, then get, I get what I set. 3. if I set twice then get, I get the second thing I set.

He’s right. These are common sense. Here how Scalaz expresses it in code:

```
trait LensLaw {
def identity(a: A)(implicit A: Equal[A], ev: F[Store[B, A]] =:= Id[Store[B, A]]): Boolean = {
val c = run(a)
A.equal(c.put(c.pos), a)
}
def retention(a: A, b: B)(implicit B: Equal[B], ev: F[Store[B, A]] =:= Id[Store[B, A]]): Boolean =
B.equal(run(run(a) put b).pos, b)
def doubleSet(a: A, b1: B, b2: B)(implicit A: Equal[A], ev: F[Store[B, A]] =:= Id[Store[B, A]]) = {
val r = run(a)
A.equal(run(r put b1) put b2, r put b2)
}
}
```

By making arbitrary turtles we can check if our `turtleX`

is ok. We’ll skip it, but make sure you don’t define weird lens that break the law.

There’s an article by Jordan West titled An Introduction to Lenses in Scalaz, which I kind of skimmed and looks like Scalaz 6.

There’s a video by Edward Kmett’s Lenses: A Functional Imperative presented at the Boston Area Scala Enthusiasts (BASE).

Finally, there’s a compiler plugin by Gerolf Seitz that generates lenses: gseitz/Lensed. The project seems to be at experimental stage, but it does show the potential of macro or compiler generating lenses instead of hand-coding them.

We’ll pick it up from here later.

learning Scalaz — Lens