Skip to content

Latest commit

 

History

562 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

cats-eo

CI Maven Central Scaladoc License

cats-eo is an existential optics library for Scala 3, layered on cats. One Optic[S, T, A, B, F] trait parameterised over a carrier F[_, _] unifies every optic family; cross-family composition goes through Composer[F, G] bridges instead of N² hand-written .andThen overloads.

Install

libraryDependencies += "dev.constructive" %% "cats-eo" % "0.18.0"
// Optional submodules:
libraryDependencies += "dev.constructive" %% "cats-eo-laws"         % "0.18.0" % Test
libraryDependencies += "dev.constructive" %% "cats-eo-generics"     % "0.18.0"
libraryDependencies += "dev.constructive" %% "cats-eo-schemes"      % "0.18.0"
libraryDependencies += "dev.constructive" %% "cats-eo-schemes-laws" % "0.18.0" % Test
libraryDependencies += "dev.constructive" %% "cats-eo-circe"        % "0.18.0"
libraryDependencies += "dev.constructive" %% "cats-eo-avro"         % "0.18.0"
libraryDependencies += "dev.constructive" %% "cats-eo-jsoniter"     % "0.18.0"
libraryDependencies += "dev.constructive" %% "cats-eo-zio"          % "0.18.0"
libraryDependencies += "dev.constructive" %% "cats-eo-kyo"          % "0.18.0" // JDK 25

Requires Scala 3.8.x on JDK 17, 21, or 25 — except cats-eo-kyo, which requires JDK 25 (kyo 1.0.0-RC5+ ships Java-25-only bytecode).

60-second tour

import dev.constructive.eo.optics.Lens
import dev.constructive.eo.optics.Optic.*
import dev.constructive.eo.generics.lens

case class Address(street: String, zip: Int)
case class Person(name: String, address: Address)

// Hand-written Lens:
val streetL = Lens[Address, String](_.street, (a, s) => a.copy(street = s))

// Macro-derived Lens, composed across two case classes:
val personStreet = lens[Person](_.address).andThen(streetL)

val alice = Person("Alice", Address("Main St", 12345))
personStreet.get(alice)                       // "Main St"
personStreet.replace("Broadway")(alice)       // address.street := "Broadway"
personStreet.modify(_.toUpperCase)(alice)     // address.street := "MAIN ST"

What's in cats-eo

  • Iso — a bijective one-focus optic; the carrier is Forgetful.
  • Lens — a one-focus optic into an always-present field of a product.
  • Prism — a one-focus optic into a sum-type branch.
  • Optional — a one-focus optic where the focus may be absent.
  • AffineFold — a read-only Optional; partial projection without a write side.
  • Getter — a read-only one-focus projection.
  • Modify — a write-only optic; modify without observing.
  • Fold — N foci summarised through a Monoid.
  • Traversal — N foci, each individually modifiable, via .each over the MultiFocus[PSVec] carrier.
  • MultiFocus — classifier-shaped update where the whole F[A] is visible (adaptive KNN, one-vs-rest), plus Kaleidoscope-style aggregation universals (.collectMap / .collectList).
  • Grate — the dual of Lens; lifts a function on the focus to a function on the whole structure.
  • Review — the reverse-only half of a Prism; build, never observe.
  • Unfold — the build-only many optic (embed: F[B] => T); assemble one whole from an F-layer of parts — the algebra of a recursion scheme.
  • JsonPrism — cursor-backed JSON optic with observable-by-default Ior failures; multi-field foci via .fields.
  • JsonTraversal — .each traversal across JSON arrays, with the same .fields multi-field flavour.
  • AvroPrism — schema-aware Avro optic over IndexedRecord, with the same Ior failure surface as JsonPrism plus a .union[Branch] macro for Avro union types. Triple input — parsed record, binary wire bytes, or Avro JSON.
  • AvroFieldsPrism — multi- field flavour of AvroPrism.
  • AvroTraversal — .each traversal across Avro arrays.
  • AvroFieldsTraversal — multi-field flavour of AvroTraversal.
  • JsoniterPrism — AST-free JSON-bytes optic over jsoniter-scala, with the same cursor sugar and Ior failure surface as JsonPrism.
  • Recursion schemes — cata / ana / hylo and the full typed zoo (para, apo, histo, futu, zygo, …) as composable optics (cats-eo-schemes, laws in cats-eo-schemes-laws).
  • ZIO integration — ZEnvironment service lens, Ref / TRef / TMap focus ops, ZLayer projection through CanGet, Chunk element optics, and optional sub-packages for zio-schema (AccessorBuilder optics, the untyped DynamicValue kit, BinaryCodec byte faces), zio-json (AST optics + JsonCursor bridge), and zio-prelude (ZValidation) (cats-eo-zio).
  • Kyo integration — TypeMap service lens, Env / Layer / Var focus ops, Record.iso / Record.lens for kyo Records, and the optional kyo-schema bridge: Focus → optics, codec byte-face prisms, and optics over the untyped Structure.Value tree (cats-eo-kyo, JDK 25).

Every optic ships a discipline-checked law set in cats-eo-laws, so downstream projects can checkAll custom instances the same way they do for cats typeclasses.

Where to go next

Project status

0.1.0 is the first public release. Binary compatibility is guaranteed within the 0.1.x series via MiMa starting at 0.1.1 (the 0.1.0 publish has no prior version to compare against). Pre-1.0, expect surface refinements as we learn from real users; each non-bugfix release will list breaking changes in CHANGELOG.md.

License

Apache License 2.0. See LICENSE.

Acknowledgements

  • cats — the typeclass foundation every carrier instance plugs into.
  • Monocle — the prior art the optic-family vocabulary descends from, and the benchmark baseline.
  • Hearth — the macro-commons library that powers cats-eo-generics.
  • kindlings — the Hearth-powered codec-derivation library backing cats-eo-circe (kindlings-circe-derivation) and cats-eo-avro (kindlings-avro-derivation).
  • discipline — the rule-set harness behind cats-eo-laws.

About

Existential Optics Library for Scala3 based on cats

Topics

Resources

Contributing

Stars

25 stars

Watchers

3 watching

Forks

Releases

Used by

Contributors

Languages