Skip to main content
Version: 2.x

Using Optics

We can use optics to work with our data structures using the get, set, and update operators on Optic.

import zio._
import zio.optics._

case class Person(name: String, age: Int)

object Person {
val age: Lens[Person, Int] =
Lens(
person => Right(person.age),
age => person => Right(person.copy(age = age))
)
}

val person = Person("Jane Doe", 42)
// person: Person = Person(name = "Jane Doe", age = 42)

Person.age.get(person)
// res0: optics.package.OpticResult[Nothing, Int] = Right(value = 42)

Person.age.set(43)(person)
// res1: optics.package.OpticResult[Nothing, Person] = Right(
// value = Person(name = "Jane Doe", age = 43)
// )

Person.age.update(person)(_ + 1)
// res2: optics.package.OpticResult[Nothing, Person] = Right(
// value = Person(name = "Jane Doe", age = 43)
// )

In addition to this, ZIO Optics provides support for accessing values directly using "dot" syntax with the optic operator.

val map: Map[String, Either[String, Chunk[Int]]] =
???

val updated: Either[OpticFailure, Map[String, Either[String, Chunk[Int]]]] =
map.optic.key("key").right.at(0).update(_ + 1)

Note that this syntax is currently only available for optics defined in ZIO Optics. When automatic derivation of optics is introduced this syntax will be supported for user defined data structures as well.