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.