dev.constructive.eo
Existential Optics for Scala 3 — the capability layer.
This root package hosts the '''capability traits''' (CanGet, CanGetOption, CanModify, CanFold, CanPut, CanPlace, CanReverseGet, CanTransform, CanModifyA, CanModifyF) that consuming code demands instead of concrete optic types: a method that reads takes a CanGet[S, A], never a Lens. Concrete optics (optics) are for construction and composition; capabilities are for use — one optic given per (S, A) pair keeps summoning unambiguous. recast re-brands an optic's phantom slots where soundness allows.
Attributes
Members list
Packages
Gate typeclasses keyed by carrier: Accessor (total read), PartialAccessor (read that may miss), ReverseAccessor (build back from the write side). Signatures that take an Optic[…, F] plus one of these on F must list the optic '''first''' in the same using clause — left-to-right resolution pins F before the gate is searched.
Gate typeclasses keyed by carrier: Accessor (total read), PartialAccessor (read that may miss), ReverseAccessor (build back from the write side). Signatures that take an Optic[…, F] plus one of these on F must list the optic '''first''' in the same using clause — left-to-right resolution pins F before the gate is searched.
Attributes
Cross-representation optics bridging native Scala types and their Apache Avro on-the-wire form.
Cross-representation optics bridging native Scala types and their Apache Avro on-the-wire form.
The entry point is AvroPrism.codecPrism (read-aloud API parallel to dev.constructive.eo.circe.codecPrism):
import dev.constructive.eo.avro.{AvroCodec, codecPrism}
import hearth.kindlings.avroderivation.AvroEncoder.derived
import hearth.kindlings.avroderivation.AvroDecoder.derived
import hearth.kindlings.avroderivation.AvroSchemaFor.derived
case class Person(name: String, age: Int)
// `given AvroCodec[Person]` falls out automatically from kindlings'
// derived `AvroEncoder[Person]`, `AvroDecoder[Person]`, `AvroSchemaFor[Person]`.
val personPrism: AvroPrism[Person] = codecPrism[Person]
val namePrism: AvroPrism[String] = personPrism.field(_.name)
namePrism.modify(_.toUpperCase)(payloadBytes)
// → the same Array[Byte] payload, with `name` upper-cased in
// place — no Person (nor any root record) ever materialised.
namePrism.record.modify(_.toUpperCase)(record)
// → the IndexedRecord-carried face, with Ior diagnostics.
The default carrier is the binary wire form itself (Array[Byte], mirroring dev.constructive.eo.jsoniter.JsoniterPrism); the record-carried face behind .record follows dev.constructive.eo.circe's architecture decisions on Json: IndexedRecord plays the role of Json, AvroCodec plays the role of (io.circe.Encoder[A], io.circe.Decoder[A]), and AvroFailure plays the role of JsonFailure.
'''Carrier note.''' Both AvroRecordPrism and eo-circe's JsonPrism are Affine-carried — lawful Optionals whose composed / upcast writes preserve siblings. A drilled focus is an Optional, so the carrier widens to Affine (via the Composer on composition) rather than pretending to be a Prism; the two record faces stay in step.
'''Deliberate duplication.''' PathStep is duplicated, not shared with eo-circe — the UnionBranch case is Avro-only and forcing it into eo-circe would pollute that module. See PathStep's class doc.
Attributes
Cross-representation optics bridging native Scala types and their circe-serialised form.
Cross-representation optics bridging native Scala types and their circe-serialised form.
The entry point is JsonPrism.apply (aliased as codecPrism for the read-aloud API):
val personPrism: JsonPrism[Person] = codecPrism[Person]
val streetPrism: JsonPrism[String] =
personPrism.field(_.address).field(_.street)
streetPrism.modify(_.toUpperCase)(personJson)
// → Ior.Right of the same Json, with .address.street upper-cased —
// no Person ever materialised.
Attributes
The composition seam: AssociativeFunctor powers the generic Optic.andThen (threading an inner carrier through an outer one), Composer names the carrier-pair-specific fusions, Morph re-expresses an optic over a different carrier so cross-carrier andThen can pick a direction, and ReadCompose routes read-only collapses (getter ∘ getter and friends) without building intermediate structure.
The composition seam: AssociativeFunctor powers the generic Optic.andThen (threading an inner carrier through an outer one), Composer names the carrier-pair-specific fusions, Morph re-expresses an optic over a different carrier so cross-carrier andThen can pick a direction, and ReadCompose routes read-only collapses (getter ∘ getter and friends) without building intermediate structure.
Attributes
Carriers — the F[_, _] shapes an optics.Optic's to / from run through: Direct (plain focus, no leftover), Either (prism miss), Affine (miss '''or''' hit-with-context), Forget / opaque ForgetK (read-only collapse), ModifyF (effectful write), MultiFocus / opaque MultiFocusK (many foci), plus the perf substrate (PSVec and the array builders). Each carrier's companion hosts its typeclass instances, so composition resolves with no imports.
Carriers — the F[_, _] shapes an optics.Optic's to / from run through: Direct (plain focus, no leftover), Either (prism miss), Affine (miss '''or''' hit-with-context), Forget / opaque ForgetK (read-only collapse), ModifyF (effectful write), MultiFocus / opaque MultiFocusK (many foci), plus the perf substrate (PSVec and the array builders). Each carrier's companion hosts its typeclass instances, so composition resolves with no imports.
Attributes
Weakened functor hierarchy for carriers that cannot honour full map: ForgetfulFunctor, ForgetfulFold, ForgetfulApplicative and ForgetfulTraverse let read-only carriers (Forget, Direct-collapsed reads) participate in the generic composition machinery by "mapping" in ways that may legally discard or refuse the function.
Weakened functor hierarchy for carriers that cannot honour full map: ForgetfulFunctor, ForgetfulFold, ForgetfulApplicative and ForgetfulTraverse let read-only carriers (Forget, Direct-collapsed reads) participate in the generic composition machinery by "mapping" in ways that may legally discard or refuse the function.
Attributes
Auto-derivation entry points for EO optics — Scala 3 quoted macros for Lens / Prism / Plated. Scaffolds on Mateusz Kubuszok's hearth macro-commons library.
Auto-derivation entry points for EO optics — Scala 3 quoted macros for Lens / Prism / Plated. Scaffolds on Mateusz Kubuszok's hearth macro-commons library.
Derived setters call the primary constructor directly (new S(...), never .copy) — uniform across case classes and enum cases, but the emitted call carries no outer accessor, so derive only for '''top-level''' ADTs, not types nested inside a class.
Attributes
Byte-level JSON optics over jsoniter-scala: JsoniterPrism and JsoniterTraversal focus a JSONPath '''directly in the encoded byte buffer''' — scanning for the span, decoding only the focused slice, and splicing writes back — so reads and writes never materialise the full document AST.
Byte-level JSON optics over jsoniter-scala: JsoniterPrism and JsoniterTraversal focus a JSONPath '''directly in the encoded byte buffer''' — scanning for the span, decoding only the focused slice, and splicing writes back — so reads and writes never materialise the full document AST.
Attributes
Law definitions for every optic family — one trait per shape (LensLaws, PrismLaws, IsoLaws, OptionalLaws, TraversalLaws, FoldLaws, GetterLaws, ModifyLaws, MultiFocusLaws, PlatedLaws, UnfoldLaws, SeamLaws, …), each method one equation. Reusable by downstream projects; the ScalaCheck/specs2 bundles live in laws.discipline, with eo-internal seam laws under laws.eo, carrier laws under laws.data and typeclass laws under laws.typeclass.
Law definitions for every optic family — one trait per shape (LensLaws, PrismLaws, IsoLaws, OptionalLaws, TraversalLaws, FoldLaws, GetterLaws, ModifyLaws, MultiFocusLaws, PlatedLaws, UnfoldLaws, SeamLaws, …), each method one equation. Reusable by downstream projects; the ScalaCheck/specs2 bundles live in laws.discipline, with eo-internal seam laws under laws.eo, carrier laws under laws.data and typeclass laws under laws.typeclass.
Attributes
The concrete optic zoo: Optic (the one existential base trait) and its named shapes — Lens, Prism, Iso, Optional, Traversal, Getter, Fold, AffineFold, Review, Modify, Unfold, Plated — each a thin class over a carrier from data with fused andThen overloads so hot compositions skip the generic seam. Construct and compose here; consume through the capability traits in dev.constructive.eo.
The concrete optic zoo: Optic (the one existential base trait) and its named shapes — Lens, Prism, Iso, Optional, Traversal, Getter, Fold, AffineFold, Review, Modify, Unfold, Plated — each a thin class over a carrier from data with fused andThen overloads so hot compositions skip the generic seam. Construct and compose here; consume through the capability traits in dev.constructive.eo.
Attributes
Recursion schemes as composable optics: Schemes.cata (fold), Schemes.ana (unfold) and Schemes.hylo (refold) over any type with a Plated instance — stack-safe, expressed as eo optics so they cross-compose with the rest of the library (ana(…).cross(cata(…)) '''is''' hylo).
Recursion schemes as composable optics: Schemes.cata (fold), Schemes.ana (unfold) and Schemes.hylo (refold) over any type with a Plated instance — stack-safe, expressed as eo optics so they cross-compose with the rest of the library (ana(…).cross(cata(…)) '''is''' hylo).
Attributes
Type members
Classlikes
Attributes
- Companion
- trait
- Source
- CanFold.scala
- Supertypes
-
class Objecttrait Matchableclass Any
- Self type
-
CanFold.type
Capability: the foci A visible in an S can be folded through a Monoid — the carrier-free surface of any optic whose carrier admits forgetful.ForgetfulFold (every readable family; the primary surface of Fold and Traversal).
Capability: the foci A visible in an S can be folded through a Monoid — the carrier-free surface of any optic whose carrier admits forgetful.ForgetfulFold (every readable family; the primary surface of Fold and Traversal).
foldMap is the kernel; headOption / length / exists / foci ride on it. foci is the carrier-free counterpart of the raw-optic all extension (which returns foci still inside their carrier, List[F[X, A]]). Prefer this trait in consuming signatures; see CanGet for the doctrine and the coherence rule.
Attributes
- Companion
- object
- Source
- CanFold.scala
- Supertypes
-
class Objecttrait Matchableclass Any
- Known subtypes
-
Show all
Attributes
- Companion
- trait
- Source
- CanGet.scala
- Supertypes
-
class Objecttrait Matchableclass Any
- Self type
-
CanGet.type
Capability: an A can be read out of an S — the carrier-free surface of any optic whose carrier admits accessor.Accessor (Lens, Iso, Getter).
Capability: an A can be read out of an S — the carrier-free surface of any optic whose carrier admits accessor.Accessor (Lens, Iso, Getter).
This is the type to name in a consuming signature: leave the subject generic and demand only the evidence the method needs — def render[T](t: T)(using id: CanGet[T, OrderId]). Concrete optic types belong where optics are constructed and composed. One optic given per (S, A) pair should be in scope at a call site — capabilities follow ordinary typeclass coherence; newtype same-typed foci apart rather than relying on implicit priority to pick between them.
Attributes
- Companion
- object
- Source
- CanGet.scala
- Supertypes
-
class Objecttrait Matchableclass Any
- Known subtypes
-
Capability: an A may be read out of an S — the carrier-free surface of any optic whose carrier admits accessor.PartialAccessor (Prism, Optional, AffineFold).
Capability: an A may be read out of an S — the carrier-free surface of any optic whose carrier admits accessor.PartialAccessor (Prism, Optional, AffineFold).
Prefer this trait in consuming signatures; see CanGet for the doctrine and the one-optic- given-per-(S, A) coherence rule.
Attributes
- Companion
- object
- Source
- CanGetOption.scala
- Supertypes
-
class Objecttrait Matchableclass Any
- Known subtypes
-
Attributes
- Companion
- trait
- Source
- CanGetOption.scala
- Supertypes
-
class Objecttrait Matchableclass Any
- Self type
-
CanGetOption.type
Capability: the foci A inside an S can be rewritten effectfully under any Applicative[G] — the carrier-free surface of any optic whose carrier admits forgetful.ForgetfulTraverse[F, Applicative] (Lens, Prism, Optional, Traversal, Fold).
Capability: the foci A inside an S can be rewritten effectfully under any Applicative[G] — the carrier-free surface of any optic whose carrier admits forgetful.ForgetfulTraverse[F, Applicative] (Lens, Prism, Optional, Traversal, Fold).
Prefer this trait in consuming signatures; the monomorphic CanModifyA alias covers the common case. For collecting the foci without effects, CanFold.foci is the carrier-free counterpart of the raw-optic all extension. See CanGet for the doctrine and the coherence rule.
Attributes
- Companion
- object
- Source
- CanModifyA.scala
- Supertypes
-
class Objecttrait Matchableclass Any
Attributes
- Companion
- trait
- Source
- CanModifyA.scala
- Supertypes
-
class Objecttrait Matchableclass Any
- Self type
-
CanModifyAP.type
Attributes
- Companion
- trait
- Source
- CanModifyF.scala
- Supertypes
-
class Objecttrait Matchableclass Any
- Self type
-
CanModifyFP.type
Capability: the focused A inside an S can be rewritten effectfully under any Functor[G] — the carrier-free surface of any optic whose carrier admits forgetful.ForgetfulTraverse[F, Functor] (today: Lens).
Capability: the focused A inside an S can be rewritten effectfully under any Functor[G] — the carrier-free surface of any optic whose carrier admits forgetful.ForgetfulTraverse[F, Functor] (today: Lens).
Prefer this trait in consuming signatures; the monomorphic CanModifyF alias covers the common case. See CanGet for the doctrine and the coherence rule.
Attributes
- Companion
- object
- Source
- CanModifyF.scala
- Supertypes
-
class Objecttrait Matchableclass Any
Attributes
- Companion
- trait
- Source
- CanModify.scala
- Supertypes
-
class Objecttrait Matchableclass Any
- Self type
-
CanModifyP.type
Capability: the focused A inside an S can be rewritten to a B, producing a T — the carrier-free surface of any optic whose carrier admits forgetful.ForgetfulFunctor (every writable family: Lens, Iso, Prism, Optional, Traversal, Modify).
Capability: the focused A inside an S can be rewritten to a B, producing a T — the carrier-free surface of any optic whose carrier admits forgetful.ForgetfulFunctor (every writable family: Lens, Iso, Prism, Optional, Traversal, Modify).
Prefer this trait in consuming signatures; the monomorphic CanModify alias covers the common S = T, A = B case. A read-then-write method should demand ONE CanModify (whose modify observes and rewrites in a single pass) rather than split CanGet + CanModify evidence — nothing ties two separately-summoned capabilities to the same optic. See CanGet for the doctrine and the coherence rule.
Attributes
- Companion
- object
- Source
- CanModify.scala
- Supertypes
-
class Objecttrait Matchableclass Any
- Known subtypes
-
Show all
Capability: a B can be written into an already-built T — the carrier-free surface of the place / transfer extensions.
Capability: a B can be written into an already-built T — the carrier-free surface of the place / transfer extensions.
Unlike its siblings this capability has NO derived given: the extensions additionally require T => F[X, B] evidence over the optic's existential X, which a generic optic given does not refine. Construct it explicitly at the seam instead — CanPlace.from(myLens) — and pass it along. See CanGet for the doctrine and the coherence rule.
Attributes
- Companion
- object
- Source
- CanPlace.scala
- Supertypes
-
class Objecttrait Matchableclass Any
Attributes
- Companion
- trait
- Source
- CanPlace.scala
- Supertypes
-
class Objecttrait Matchableclass Any
- Self type
-
CanPlace.type
Attributes
- Companion
- trait
- Source
- CanPut.scala
- Supertypes
-
class Objecttrait Matchableclass Any
- Self type
-
CanPutP.type
Capability: a T can be constructed directly from an A, running f: A => B at the focus — the carrier-free surface of any optic whose carrier admits forgetful.ForgetfulApplicative (today: the Direct-carrier families, and Folds over an Applicative).
Capability: a T can be constructed directly from an A, running f: A => B at the focus — the carrier-free surface of any optic whose carrier admits forgetful.ForgetfulApplicative (today: the Direct-carrier families, and Folds over an Applicative).
Prefer this trait in consuming signatures; the monomorphic CanPut alias covers A = B. See CanGet for the doctrine and the coherence rule.
Attributes
- Companion
- object
- Source
- CanPut.scala
- Supertypes
-
class Objecttrait Matchableclass Any
Capability: a T can be built from a B — the carrier-free surface of any optic whose carrier admits accessor.ReverseAccessor (Iso, Prism, Review).
Capability: a T can be built from a B — the carrier-free surface of any optic whose carrier admits accessor.ReverseAccessor (Iso, Prism, Review).
Prefer this trait in consuming signatures; see CanGet for the doctrine and the coherence rule.
Attributes
- Companion
- object
- Source
- CanReverseGet.scala
- Supertypes
-
class Objecttrait Matchableclass Any
- Known subtypes
-
Attributes
- Companion
- trait
- Source
- CanReverseGet.scala
- Supertypes
-
class Objecttrait Matchableclass Any
- Self type
-
CanReverseGet.type
Attributes
- Companion
- trait
- Source
- CanTransform.scala
- Supertypes
-
class Objecttrait Matchableclass Any
- Self type
-
CanTransform.type
Capability: a D at the focus of an already-built T can be transformed via D => B — the carrier-free surface of the transform extension (the generalised CanPlace).
Capability: a D at the focus of an already-built T can be transformed via D => B — the carrier-free surface of the transform extension (the generalised CanPlace).
Like CanPlace this capability has NO derived given — the extension requires T => F[X, D] evidence over the optic's existential X. Construct it explicitly: CanTransform.from(myLens). See CanGet for the doctrine and the coherence rule.
Attributes
- Companion
- object
- Source
- CanTransform.scala
- Supertypes
-
class Objecttrait Matchableclass Any
Types
Monomorphic CanModifyP (S = T, A = B) — the shape most consuming signatures want: def adjustTimes[T](using cm: CanModify[T, DateTime]): T => T = cm.modify(adjustTime).
Monomorphic CanModifyP (S = T, A = B) — the shape most consuming signatures want: def adjustTimes[T](using cm: CanModify[T, DateTime]): T => T = cm.modify(adjustTime).
Attributes
- Source
- CanModify.scala
Monomorphic CanModifyAP (S = T, A = B).
Monomorphic CanModifyFP (S = T, A = B).