Mix this trait into the companion object of a case class or a sealed trait to get the class's optics without writing them: a Lens for each field of a case class, named after the field, and a Prism for each case of a sealed trait (or, on Scala 3, an enum), named after the case with its first letter in lower case (Paperback gives paperback). They are the members of optics. On Scala 3 they are also members of the companion itself (Book.title), through a given conversion. A member that the companion defines itself takes precedence there, and the derived optic stays available on optics. Direct access goes through an implicit conversion, so Scala 3 gives a feature warning at each use unless scala.language.implicitConversions is imported, as the first example does.
An implicit Schema of the class must be in scope where optics is used; a schema defined in the companion is. For a type that is not the class of a companion, such as Box[Int] or a type alias, use DerivedOptics.Of. On Scala 3, a value class whose schema is a wrapper (built with transform) gets a working lens only when its field is named value. Opaque types are not supported yet.
The optics are built the first time optics is evaluated and kept in a global cache keyed by the type's printed name. Every companion for the same type shares the optics built from the first schema used, and so do different types that print the same, such as two local classes named Book in different methods: the second then fails with a ClassCastException or No optic found (a bug, see docs/dev/issues.md).
A known problem, described in docs/dev/issues.md: on Scala 2, optics compiles only inside the zio.blocks.schema package, so the examples below are compiled on Scala 3 only.
// scala-3-only
import scala.language.implicitConversions
case class Book(title: String, pages: Int)
object Book extends DerivedOptics {
implicit val schema: Schema[Book] = Schema.derived
}
val title: Lens[Book, String] = Book.optics.title
val pages: Lens[Book, Int] = Book.pages // direct access, Scala 3 only
// scala-3-only
sealed trait Format
case class Paperback(pages: Int) extends Format
case class Ebook(sizeMb: Double) extends Format
object Format extends DerivedOptics {
implicit val schema: Schema[Format] = Schema.derived
}
val paperback: Prism[Format, Paperback] = Format.optics.paperback
// scala-3-only
case class PageCount(value: Int) extends AnyVal
object PageCount extends DerivedOptics {
// a wrapper schema, built with `transform`
implicit val schema: Schema[PageCount] = Schema[Int].transform(PageCount(_), _.value)
}
val value: Lens[PageCount, Int] = PageCount.optics.value
Attributes
- See also
- Companion
- object
- Source
- DerivedOptics.scala
- Graph
-
- Supertypes