dev.constructive.eo.optics
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
Members list
Type members
Classlikes
Constructors for AffineFold.
Constructors for AffineFold.
Attributes
- Source
- AffineFold.scala
- Supertypes
-
class Objecttrait Matchableclass Any
- Self type
-
AffineFold.type
Concrete Optic subclass for an isomorphism. Stores get / reverseGet directly so the hot path skips the Accessor[Direct] / ReverseAccessor[Direct] typeclass dispatches the generic extensions would perform — same storage shape as Monocle's Iso. Returned by Iso.apply so hand-written isos pick up the fused path automatically.
Concrete Optic subclass for an isomorphism. Stores get / reverseGet directly so the hot path skips the Accessor[Direct] / ReverseAccessor[Direct] typeclass dispatches the generic extensions would perform — same storage shape as Monocle's Iso. Returned by Iso.apply so hand-written isos pick up the fused path automatically.
Attributes
- Source
- Iso.scala
- Supertypes
-
class Objecttrait Matchableclass AnyShow all
Constructors for Fold — read-only multi-focus optic, backed by Forget[F] (Forget[F][X, A] = F[A]). T = Unit rules out the write path; .foldMap is the consumption surface. Fold.select(p) narrows to a one-element Option stream. The build-only dual on the same carrier — assemble a T from an F-layer — is Unfold.
Constructors for Fold — read-only multi-focus optic, backed by Forget[F] (Forget[F][X, A] = F[A]). T = Unit rules out the write path; .foldMap is the consumption surface. Fold.select(p) narrows to a one-element Option stream. The build-only dual on the same carrier — assemble a T from an F-layer — is Unfold.
Both constructors return the concrete ForgetFold subclass so a hand-written Fold picks up its eager, carrier-free foldMap member (see ForgetFold.foldMap).
Attributes
- Source
- Fold.scala
- Supertypes
-
class Objecttrait Matchableclass Any
- Self type
-
Fold.type
Concrete Optic subclass for Fold, storing the source projection to and the underlying Foldable[F] directly. This lets the terminal foldMap fold the focus eagerly through the captured Foldable[F], skipping both the per-call ForgetfulFold[Forget[F]] summon and the intermediate S => M closure the generic Optic.foldMap extension builds — the same specialisation GetReplaceLens / Modify / MultiFocusSingleton apply to their hot paths.
Concrete Optic subclass for Fold, storing the source projection to and the underlying Foldable[F] directly. This lets the terminal foldMap fold the focus eagerly through the captured Foldable[F], skipping both the per-call ForgetfulFold[Forget[F]] summon and the intermediate S => M closure the generic Optic.foldMap extension builds — the same specialisation GetReplaceLens / Modify / MultiFocusSingleton apply to their hot paths.
Returned by every Fold.* constructor so hand-written folds pick up the fast path automatically. A composed Fold (the result of .andThen) surfaces as the erased Optic[…, Forget[F]] and keeps the generic extension — the same trade-off GetReplaceLens accepts.
Attributes
- Source
- Fold.scala
- Supertypes
Concrete Optic subclass storing get and enplace directly, enabling the fused-andThen overloads below to bypass the Tuple2 carrier entirely. Returned by every Lens.* constructor so hand-written lenses pick up the fused hot path automatically.
Concrete Optic subclass storing get and enplace directly, enabling the fused-andThen overloads below to bypass the Tuple2 carrier entirely. Returned by every Lens.* constructor so hand-written lenses pick up the fused hot path automatically.
Attributes
- Source
- Lens.scala
- Supertypes
-
class Objecttrait Matchableclass AnyShow all
Concrete Optic subclass for a read-only getter. A final class storing get directly — NOT an abstract class with an abstract get: the CI A/B showed composed-getter dispatch through the abstract-class form costs ~1.8x (eoGet_3 5.1ns final vs 11.5ns abstract) even with a fused andThen, while every fused path that stayed a concrete class (GetReplaceLens lens-reuse) was flat. The hot path skips the Accessor[Direct] dispatch the generic extension would perform — the same shape as BijectionIso / GetReplaceLens. Returned by Getter.apply so hand-written getters pick up the fused path automatically.
Concrete Optic subclass for a read-only getter. A final class storing get directly — NOT an abstract class with an abstract get: the CI A/B showed composed-getter dispatch through the abstract-class form costs ~1.8x (eoGet_3 5.1ns final vs 11.5ns abstract) even with a fused andThen, while every fused path that stayed a concrete class (GetReplaceLens lens-reuse) was flat. The hot path skips the Accessor[Direct] dispatch the generic extension would perform — the same shape as BijectionIso / GetReplaceLens. Returned by Getter.apply so hand-written getters pick up the fused path automatically.
Attributes
- Companion
- object
- Source
- Getter.scala
- Supertypes
Constructor for Getter — read-only single-focus optic, backed by Direct with T = B = Unit. .get(s) is the only meaningful operation; the write path is vestigial.
Constructor for Getter — read-only single-focus optic, backed by Direct with T = B = Unit. .get(s) is the only meaningful operation; the write path is vestigial.
Both the leftover T and the back-focus B are Unit, which makes the read-only-ness explicit in the type (there is no B to put back). Getter.apply returns a concrete Getter, so a Getter composes with another Getter through the ordinary andThen (the fused Getter.andThen) — g1.andThen(g2) reads s => g2.get(g1.get(s)) — exactly as Iso / Lens compose via their own fused subclasses.
Attributes
- Companion
- class
- Source
- Getter.scala
- Supertypes
-
class Objecttrait Matchableclass Any
- Self type
-
Getter.type
Constructor for Iso — a bijective single-focus optic, backed by Direct. An Iso[S, A] (short for Optic[S, S, A, A, Direct]) encodes a data-shape bijection. Direct[X, A] = A carries no leftover, so every Iso operation reduces to plain function application.
Constructor for Iso — a bijective single-focus optic, backed by Direct. An Iso[S, A] (short for Optic[S, S, A, A, Direct]) encodes a data-shape bijection. Direct[X, A] = A carries no leftover, so every Iso operation reduces to plain function application.
Attributes
Constructors for Lens — the always-present single-focus optic, backed by Tuple2. A Lens[S, A] (short for Optic[S, S, A, A, Tuple2]) reads a field via get(s) and rewrites it via modify / replace. The eo-generics module's lens[S](_.field) macro derives both.
Constructors for Lens — the always-present single-focus optic, backed by Tuple2. A Lens[S, A] (short for Optic[S, S, A, A, Tuple2]) reads a field via get(s) and rewrites it via modify / replace. The eo-generics module's lens[S](_.field) macro derives both.
Attributes
- Source
- Lens.scala
- Supertypes
-
class Objecttrait Matchableclass Any
- Self type
-
Lens.type
Concrete Optic subclass storing tear (getOrModify) and mend (reverseGet) directly. The fused-andThen overloads pattern-match once and skip the generic AssociativeFunctor[Either] round-trip. All Prism.* constructors return this type.
Concrete Optic subclass storing tear (getOrModify) and mend (reverseGet) directly. The fused-andThen overloads pattern-match once and skip the generic AssociativeFunctor[Either] round-trip. All Prism.* constructors return this type.
Attributes
- Source
- Prism.scala
- Supertypes
-
class Objecttrait Matchableclass AnyShow all
Concrete Optic subclass for a write-only modifier. Stores the writer modifyFn directly (so the hot path skips the ModifyF carrier round-trip the generic extension performs) and carries a fused andThen for modify∘modify composition — the same shape as GetReplaceLens / Getter. Returned by Modify.apply so hand-written modifiers pick up the fused path automatically.
Concrete Optic subclass for a write-only modifier. Stores the writer modifyFn directly (so the hot path skips the ModifyF carrier round-trip the generic extension performs) and carries a fused andThen for modify∘modify composition — the same shape as GetReplaceLens / Getter. Returned by Modify.apply so hand-written modifiers pick up the fused path automatically.
Attributes
- Companion
- object
- Source
- Modify.scala
- Supertypes
-
class Objecttrait Matchableclass Any
Constructor for Modify — write-only single-focus optic, backed by ModifyF. The caller applies a function at the focus but cannot read it back; useful when observation would leak information or when the focus is genuinely unreadable (e.g. inside a closure).
Constructor for Modify — write-only single-focus optic, backed by ModifyF. The caller applies a function at the focus but cannot read it back; useful when observation would leak information or when the focus is genuinely unreadable (e.g. inside a closure).
Modify.apply returns a concrete Modify, so a Modify composes with another Modify through the ordinary andThen (the fused Modify.andThen) — s1.andThen(s2).modify(f) == s1.modify(s2.modify(f)) — exactly as Iso / Lens / Getter compose via their own fused subclasses, bypassing the generic AssociativeFunctor[ModifyF] round-trip.
Attributes
- Companion
- class
- Source
- Modify.scala
- Supertypes
-
class Objecttrait Matchableclass Any
- Self type
-
Modify.type
Existential encoding of a profunctor optic — the single trait behind every optic family in cats-eo. The optic is a pair of functions (S => F[X, A], F[X, B] => T) over a carrier F[_, _] and an existential X that threads the leftover information needed to rebuild T. Each family picks a different carrier (Tuple2 for Lens, Either for Prism, Affine for Optional, …). Operations live in the companion as capability-gated extensions; each extension's (using …) clause names the typeclass on F that unlocks it.
Existential encoding of a profunctor optic — the single trait behind every optic family in cats-eo. The optic is a pair of functions (S => F[X, A], F[X, B] => T) over a carrier F[_, _] and an existential X that threads the leftover information needed to rebuild T. Each family picks a different carrier (Tuple2 for Lens, Either for Prism, Affine for Optional, …). Operations live in the companion as capability-gated extensions; each extension's (using …) clause names the typeclass on F that unlocks it.
Type parameters
- A
-
focus read out of
S - B
-
focus written back to produce
T(often= A) - F
-
two-argument carrier; capabilities scale with the typeclasses
Fadmits. - S
-
source type being observed / modified
- T
-
result type after modification (often
= S)
Attributes
- See also
- Companion
- object
- Source
- Optic.scala
- Supertypes
-
class Objecttrait Matchableclass Any
- Known subtypes
- Self type
-
Companion for Optic. Hosts the profunctor instances and the capability-gated extension catalogue — .get, .modify, .replace, .foldMap, .modifyA, .all, .reverseGet, .getOption, .put, .transform, .place, .transfer, .andThen (carrier-morphing plus the read-only / AffineFold / Modify / Review / Unfold collapses), .readOnly, .cross, .morph, .headOption, .length, .exists. Adding a new carrier means supplying the typeclass instances of the operations it should support.
Companion for Optic. Hosts the profunctor instances and the capability-gated extension catalogue — .get, .modify, .replace, .foldMap, .modifyA, .all, .reverseGet, .getOption, .put, .transform, .place, .transfer, .andThen (carrier-morphing plus the read-only / AffineFold / Modify / Review / Unfold collapses), .readOnly, .cross, .morph, .headOption, .length, .exists. Adding a new carrier means supplying the typeclass instances of the operations it should support.
Attributes
- Companion
- trait
- Source
- Optic.scala
- Supertypes
-
class Objecttrait Matchableclass Any
- Self type
-
Optic.type
Constructor for Optional — the conditionally-present single-focus optic, backed by Affine. An Optional[S, A] (short for Optic[S, S, A, A, Affine]) encodes a field that may or may not be there. Composes freely with Lens via cross-carrier .andThen (auto-morphs through Composer[Tuple2, Affine]).
Constructor for Optional — the conditionally-present single-focus optic, backed by Affine. An Optional[S, A] (short for Optic[S, S, A, A, Affine]) encodes a field that may or may not be there. Composes freely with Lens via cross-carrier .andThen (auto-morphs through Composer[Tuple2, Affine]).
Attributes
- Companion
- class
- Source
- Optional.scala
- Supertypes
-
class Objecttrait Matchableclass Any
- Self type
-
Optional.type
Concrete Optic subclass for Optional.apply — stores getOrModify / reverseGet directly so the fused .andThen overloads can skip the generic AssociativeFunctor[Affine] round-trip whenever the other side is also a known subclass.
Concrete Optic subclass for Optional.apply — stores getOrModify / reverseGet directly so the fused .andThen overloads can skip the generic AssociativeFunctor[Affine] round-trip whenever the other side is also a known subclass.
Attributes
- Companion
- object
- Source
- Optional.scala
- Supertypes
-
class Objecttrait Matchableclass AnyShow all
Concrete Optic subclass for AffineFold — a final class storing pick directly, NOT a shared anonymous wrapper: a single anon class would host one pick.apply bytecode site for every AffineFold instance, the megamorphic-dispatch trap PrintInlining exposed on the abstract-class Getter (the JIT profiles that one site over all instances' lambdas and gives up inlining). Same storage shape as PickMendPrism (pick) and ForgetFold (read). Returned by AffineFold.apply / AffineFold.select so hand-written affine folds pick up the fused members automatically.
Concrete Optic subclass for AffineFold — a final class storing pick directly, NOT a shared anonymous wrapper: a single anon class would host one pick.apply bytecode site for every AffineFold instance, the megamorphic-dispatch trap PrintInlining exposed on the abstract-class Getter (the JIT profiles that one site over all instances' lambdas and gives up inlining). Same storage shape as PickMendPrism (pick) and ForgetFold (read). Returned by AffineFold.apply / AffineFold.select so hand-written affine folds pick up the fused members automatically.
Attributes
- Source
- AffineFold.scala
- Supertypes
-
class Objecttrait Matchableclass AnyShow all
Concrete Optic subclass for the Option-shaped Prism (Prism.optional / Prism.pOptional). Stores pick and mend directly; the fused extensions pattern-match on Option so the hot path never builds the intermediate Either[S, A] the generic MendTearPrism would.
Concrete Optic subclass for the Option-shaped Prism (Prism.optional / Prism.pOptional). Stores pick and mend directly; the fused extensions pattern-match on Option so the hot path never builds the intermediate Either[S, A] the generic MendTearPrism would.
Attributes
- Source
- Prism.scala
- Supertypes
-
class Objecttrait Matchableclass AnyShow all
A self-similar structure: a value of S whose immediate sub-terms are themselves S. The single member plate is a Traversal[S, S] focusing those immediate children — the cats-eo analogue of Haskell lens's Plated class (plate :: Traversal' a a).
A self-similar structure: a value of S whose immediate sub-terms are themselves S. The single member plate is a Traversal[S, S] focusing those immediate children — the cats-eo analogue of Haskell lens's Plated class (plate :: Traversal' a a).
The recursion combinators in the companion (Plated.transform, Plated.rewrite, Plated.children, Plated.universe) build on plate to walk the whole tree. They are stack-safe on deep trees: transform recurses on the call stack while shallow and falls back to a heap-stack machine past a depth bound, rewrite trampolines through cats.Eval, and universe / children use an explicit worklist — a degenerate 100k-deep tree is fine.
The children are carried as a PSVec (the MultiFocus[PSVec] carrier's focus vector), so the read path and the write path share one representation with no List round-trips — see childrenVec.
Get an instance by hand via Plated.fromChildren / Plated.fromChildrenVec, by deriving one with dev.constructive.eo.generics.plate[S], or — when you have already built the self-traversal as an optic — by calling .asPlated on it (see the extension methods below).
Attributes
- See also
-
Traversal.selfChildren for the underlying carrier.
- Companion
- object
- Source
- Plated.scala
- Supertypes
-
class Objecttrait Matchableclass Any
Combinators over Plated — recursion schemes faithful to Control.Lens.Plated, all stack-safe. Each is offered both as a using Plated[S] method here and as an extension on any self-traversal optic you build directly (so myPlate.transformAll(f)(s) works without a typeclass).
Combinators over Plated — recursion schemes faithful to Control.Lens.Plated, all stack-safe. Each is offered both as a using Plated[S] method here and as an extension on any self-traversal optic you build directly (so myPlate.transformAll(f)(s) works without a typeclass).
Attributes
- Companion
- trait
- Source
- Plated.scala
- Supertypes
-
class Objecttrait Matchableclass Any
- Self type
-
Plated.type
Constructors for Prism — the partial single-focus optic, backed by Either. A Prism[S, A] (short for Optic[S, S, A, A, Either]) encodes a branch of a sum type: getOption(s) succeeds when s matches, reverseGet(a) lifts back. The eo-generics module's prism[S, A] macro derives prisms on enums / sealed traits / union types.
Constructors for Prism — the partial single-focus optic, backed by Either. A Prism[S, A] (short for Optic[S, S, A, A, Either]) encodes a branch of a sum type: getOption(s) succeeds when s matches, reverseGet(a) lifts back. The eo-generics module's prism[S, A] macro derives prisms on enums / sealed traits / union types.
Attributes
- Source
- Prism.scala
- Supertypes
-
class Objecttrait Matchableclass Any
- Self type
-
Prism.type
Reverse-only counterpart to Getter — wraps reverseGet: A => S and is the exact mirror of Getter. Getter is Optic[S, Unit, A, Unit, Direct] (a real to reading S => A, vestigial from); Review is the dual Optic[Unit, S, Unit, A, Direct] — a vestigial to (reads Unit) and a real from that builds S from the focus A.
Reverse-only counterpart to Getter — wraps reverseGet: A => S and is the exact mirror of Getter. Getter is Optic[S, Unit, A, Unit, Direct] (a real to reading S => A, vestigial from); Review is the dual Optic[Unit, S, Unit, A, Direct] — a vestigial to (reads Unit) and a real from that builds S from the focus A.
It therefore IS an Optic — with source Unit the to is exactly as vestigial as Getter's from, so "pure Review has no to" is no reason to sit outside the trait. A Review composes with another Review through the fused andThen just as Getters do, and slots into the Direct-carrier optic surface.
A final class storing reverseGet directly — NOT an abstract class with an abstract member — for the same composed-dispatch reason documented on Getter.
To get the build direction out of an Iso or Prism, wrap its reverse directly — Review(iso.reverseGet) / Review(prism.mend) — rather than via a bespoke factory: an Iso/Prism already is a build direction, so cross-optic from* constructors would be redundant (eo has no Prism.fromIso etc. for the same reason).
Review builds from ONE focus; its many-rung sibling is Unfold (assemble a T from an F-layer of parts), reachable by composition through the fused andThen(Unfold) below.
Attributes
- Companion
- object
- Source
- Review.scala
- Supertypes
-
class Objecttrait Matchableclass Any
Constructors for Review.
Constructors for Review.
Attributes
- Companion
- class
- Source
- Review.scala
- Supertypes
-
class Objecttrait Matchableclass Any
- Self type
-
Review.type
Monomorphic split-combine lens (S = T, A = B). The matched source / target lets the to splitter double as the T => (X, A) evidence the mutation extensions need, so place / transfer land on the class body directly. Used by Lens.first, Lens.second, and the eo-generics lens[S](_.field) macro.
Monomorphic split-combine lens (S = T, A = B). The matched source / target lets the to splitter double as the T => (X, A) evidence the mutation extensions need, so place / transfer land on the class body directly. Used by Lens.first, Lens.second, and the eo-generics lens[S](_.field) macro.
Attributes
- Companion
- object
- Source
- Lens.scala
- Supertypes
-
class Objecttrait Matchableclass AnyShow all
Companion for SimpleLens. Hands out a transformEvidence given so the generic Optic.transform / .place / .transfer extensions pick up the same behaviour as the class-level methods.
Companion for SimpleLens. Hands out a transformEvidence given so the generic Optic.transform / .place / .transfer extensions pick up the same behaviour as the class-level methods.
Attributes
- Companion
- class
- Source
- Lens.scala
- Supertypes
-
class Objecttrait Matchableclass Any
- Self type
-
SimpleLens.type
Polymorphic split-combine lens — splitter S => (XA, A) + combiner (XA, B) => T, surfacing the complement as X = XA. Does not ship place / transfer (would require a T => (XA, B) evidence that isn't recoverable when T ≠ S); callers route through the generic Optic extensions when the evidence is available.
Polymorphic split-combine lens — splitter S => (XA, A) + combiner (XA, B) => T, surfacing the complement as X = XA. Does not ship place / transfer (would require a T => (XA, B) evidence that isn't recoverable when T ≠ S); callers route through the generic Optic extensions when the evidence is available.
Attributes
- Source
- Lens.scala
- Supertypes
-
class Objecttrait Matchableclass AnyShow all
- Known subtypes
-
Constructors for Traversal. Every constructor here — each / pEach / selfChildren and the two / three / four fixed-arity variants — rides the MultiFocus[PSVec] carrier, so they all compose through the standard .andThen in both directions (past a Lens, a Prism, another traversal, …).
Constructors for Traversal. Every constructor here — each / pEach / selfChildren and the two / three / four fixed-arity variants — rides the MultiFocus[PSVec] carrier, so they all compose through the standard .andThen in both directions (past a Lens, a Prism, another traversal, …).
Attributes
- Source
- Traversal.scala
- Supertypes
-
class Objecttrait Matchableclass Any
- Self type
-
Traversal.type
Build-only counterpart to Fold — the inhabitant of the build-only / many cell of the optic lattice, exactly as Review is Getter's build-only mirror on the total rung. Fold is Optic[S, Unit, A, Unit, Forget[F]] (a real to reading S => F[A], vestigial from); Unfold is the across-both-axes dual Optic[Unit, T, Unit, B, Forget[F]] — a vestigial to and a real from that assembles one T from a layer of parts F[B]:
Build-only counterpart to Fold — the inhabitant of the build-only / many cell of the optic lattice, exactly as Review is Getter's build-only mirror on the total rung. Fold is Optic[S, Unit, A, Unit, Forget[F]] (a real to reading S => F[A], vestigial from); Unfold is the across-both-axes dual Optic[Unit, T, Unit, B, Forget[F]] — a vestigial to and a real from that assembles one T from a layer of parts F[B]:
embed : F[B] => T // many → one: the algebra of a recursion scheme
This is the F-shape embed of a Corecursive instance (Fold's S => F[A] being the project half), and the aggregation arrow "build an Order from its line-items". Plated's plate bundles both halves inside one read-write traversal; Unfold exposes the embed half standalone, so an algebra can be carried, composed, and consumed as an optic.
'''The vestigial to.''' Read-only optics zero out their write side for free (from discards into Unit, the terminal object). The build-only dual is not free: to: Unit => F[Unit] must produce an F-layer, and there is no canonical F[Unit] without Applicative[F] (pure(())). Two constructors, two answers:
- Unfold.apply (
F: Applicative) — honest vestigialto = pure(()). Read-side operations that reachto(.modify,.foldMap, …) degrade to the singleton layer. - Unfold.algebra (no constraint) — for pattern functors (
BinF,RoseF, …), which admitFunctor/Traversebut noApplicative(purecannot pick a constructor). Itstois genuinely unreachable through the build-only surface and THROWS if forced — the same reachable-path contract asComposer.direct2forget's singleton-pickfrom.
A final class storing embed directly — NOT an abstract member — per the composed-dispatch findings on Getter / Review. Fused andThen members keep build-only chains concrete.
Attributes
- Companion
- object
- Source
- Unfold.scala
- Supertypes
Constructors for Unfold — build-only multi-focus optic, backed by Forget[F] (Forget[F][X, B] = F[B]) with S = A = Unit ruling out the read path; .embed is the consumption surface.
Constructors for Unfold — build-only multi-focus optic, backed by Forget[F] (Forget[F][X, B] = F[B]) with S = A = Unit ruling out the read path; .embed is the consumption surface.
Attributes
- Companion
- class
- Source
- Unfold.scala
- Supertypes
-
class Objecttrait Matchableclass Any
- Self type
-
Unfold.type
Types
Read-only 0-or-1-focus optic — Optic[S, Unit, A, Unit, Affine]. Both T and the write-focus B are Unit (honestly one-way, like Getter / Fold): there is no value to put back, so .modify / .replace don't apply. The surface is .getOption and .foldMap. Composes with Lens / Prism via the same Morph bridges full Optional uses (they key off the carrier, not the T slot).
Read-only 0-or-1-focus optic — Optic[S, Unit, A, Unit, Affine]. Both T and the write-focus B are Unit (honestly one-way, like Getter / Fold): there is no value to put back, so .modify / .replace don't apply. The surface is .getOption and .foldMap. Composes with Lens / Prism via the same Morph bridges full Optional uses (they key off the carrier, not the T slot).
Specialised existential X = (Unit, Unit): Affine.Hit stores snd: Unit + b: A — one reference slot less than the (S, A) payload of a full Optional, since from throws its input away anyway.
Attributes
- Source
- AffineFold.scala