Optic

dev.constructive.eo.optics.Optic
See theOptic companion trait
object Optic

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
Graph
Supertypes
class Object
trait Matchable
class Any
Self type
Optic.type

Members list

Grouped members

Operations

inline def cross[G[_, _], C, D](o: Optic[T, S, C, D, G])(using m: Morph[F, G]): Optic[B, A, C, D, m.Out]

Flip the direction of an optic — only defined when the carrier admits both Accessor[F] and ReverseAccessor[F] (i.e. iso-shaped carriers).

Flip the direction of an optic — only defined when the carrier admits both Accessor[F] and ReverseAccessor[F] (i.e. iso-shaped carriers).

Attributes

Source
Optic.scala
def exists(p: A => Boolean)(s: S): Boolean

True iff at least one focus satisfies p. Short-circuits on the first hit when the carrier's ForgetfulFold[F] is short-circuit-aware. The default Monoid[Boolean] cats exposes is conjunction (&&); we instantiate a disjunction monoid inline so a single match can win without consulting the rest.

True iff at least one focus satisfies p. Short-circuits on the first hit when the carrier's ForgetfulFold[F] is short-circuit-aware. The default Monoid[Boolean] cats exposes is conjunction (&&); we instantiate a disjunction monoid inline so a single match can win without consulting the rest.

Attributes

Source
Optic.scala
inline def foldMap[M : Monoid](f: A => M): S => M

foldMap over the focus — the primary consumption path for Fold and any other carrier with a ForgetfulFold[F] instance. Combines every focus through Monoid[M].

foldMap over the focus — the primary consumption path for Fold and any other carrier with a ForgetfulFold[F] instance. Combines every focus through Monoid[M].

Attributes

Source
Optic.scala
inline def get(s: S): A

Total read — extract the focus, available when the carrier always hits (Accessor[F]: Tuple2 for Lens, Direct for Iso / Getter). readOnly wraps the same read as a concrete Getter, the one-way view of a writable optic.

Total read — extract the focus, available when the carrier always hits (Accessor[F]: Tuple2 for Lens, Direct for Iso / Getter). readOnly wraps the same read as a concrete Getter, the one-way view of a writable optic.

Attributes

Source
Optic.scala
inline def getOption(s: S): Option[A]

Partial read — Some(focus) on hit, None on miss. Available when the carrier may miss (PartialAccessor[F]: Either for Prism, Affine for Optional / AffineFold).

Partial read — Some(focus) on hit, None on miss. Available when the carrier may miss (PartialAccessor[F]: Either for Prism, Affine for Optional / AffineFold).

Attributes

Source
Optic.scala
def headOption(s: S): Option[A]

First focus visible through the optic, if any. Available on any carrier admitting ForgetfulFold[F]Forget[F] (Fold), MultiFocus[F] (Traversal), Affine (Optional / AffineFold), Either (Prism), Tuple2 (Lens). For 0-or-1-focus carriers this is the same Option you'd get from .getOption; for multi-focus carriers it picks the first focus the underlying Foldable enumerates.

First focus visible through the optic, if any. Available on any carrier admitting ForgetfulFold[F]Forget[F] (Fold), MultiFocus[F] (Traversal), Affine (Optional / AffineFold), Either (Prism), Tuple2 (Lens). For 0-or-1-focus carriers this is the same Option you'd get from .getOption; for multi-focus carriers it picks the first focus the underlying Foldable enumerates.

Implemented via foldMap under a custom "first-Some" Monoid[Option[A]] — the same shape Monocle's Fold.headOption uses. The custom monoid short-circuits via _.orElse(_), so on a Foldable[F] whose foldMap is itself short-circuit-aware (e.g. LazyList) the walk stops at the first focus.

Attributes

Source
Optic.scala
def length(s: S): Int

Number of foci visible through the optic. O(n) in the focus count via Foldable.foldMap under Monoid[Int]. Distinct from Foldable.size only in that it routes through the carrier's ForgetfulFold[F] — same end result, available wherever foldMap is.

Number of foci visible through the optic. O(n) in the focus count via Foldable.foldMap under Monoid[Int]. Distinct from Foldable.size only in that it routes through the carrier's ForgetfulFold[F] — same end result, available wherever foldMap is.

Attributes

Source
Optic.scala
inline def modify(f: A => B): S => T

Modify (A => B) or replace (by constant B) the focus in-place. Available for every carrier with a ForgetfulFunctor[F] instance — i.e. every current optic family.

Modify (A => B) or replace (by constant B) the focus in-place. Available for every carrier with a ForgetfulFunctor[F] instance — i.e. every current optic family.

Attributes

Source
Optic.scala
inline def modifyA[G[_]](f: A => G[B])(using G: Applicative[G]): S => G[T]

Effectful modify over any Applicative[G]; unlike modifyF this variant also exposes all, which collects every visited focus via Applicative[List].

Effectful modify over any Applicative[G]; unlike modifyF this variant also exposes all, which collects every visited focus via Applicative[List].

Attributes

Source
Optic.scala
inline def modifyF[G[_]](f: A => G[B])(using G: Functor[G]): S => G[T]

Effectful modify over any Functor[G] — generalises modify to monadic / effectful A => G[B] transformations.

Effectful modify over any Functor[G] — generalises modify to monadic / effectful A => G[B] transformations.

Attributes

Source
Optic.scala
inline def place(b: B): T => T

Overwrite a T-shaped value at the focus — available when the carrier can witness T => F[X, B] (e.g. Direct, where F[X, B] = B). transfer lifts a C => B into this same shape with an extra C argument.

Overwrite a T-shaped value at the focus — available when the carrier can witness T => F[X, B] (e.g. Direct, where F[X, B] = B). transfer lifts a C => B into this same shape with an extra C argument.

Attributes

Source
Optic.scala
inline def put(f: A => B): A => T

Construct a T directly from an A, running f: A => B at the focus — available for carriers with a ForgetfulApplicative[F] instance (today: Direct).

Construct a T directly from an A, running f: A => B at the focus — available for carriers with a ForgetfulApplicative[F] instance (today: Direct).

Attributes

Source
Optic.scala
inline def readOnly: Getter[S, A]

Total read — extract the focus, available when the carrier always hits (Accessor[F]: Tuple2 for Lens, Direct for Iso / Getter). readOnly wraps the same read as a concrete Getter, the one-way view of a writable optic.

Total read — extract the focus, available when the carrier always hits (Accessor[F]: Tuple2 for Lens, Direct for Iso / Getter). readOnly wraps the same read as a concrete Getter, the one-way view of a writable optic.

Attributes

Source
Optic.scala
inline def replace(b: B): S => T

Modify (A => B) or replace (by constant B) the focus in-place. Available for every carrier with a ForgetfulFunctor[F] instance — i.e. every current optic family.

Modify (A => B) or replace (by constant B) the focus in-place. Available for every carrier with a ForgetfulFunctor[F] instance — i.e. every current optic family.

Attributes

Source
Optic.scala
def reverse: Optic[B, A, T, S, F]

Flip the direction of an optic — only defined when the carrier admits both Accessor[F] and ReverseAccessor[F] (i.e. iso-shaped carriers).

Flip the direction of an optic — only defined when the carrier admits both Accessor[F] and ReverseAccessor[F] (i.e. iso-shaped carriers).

Attributes

Source
Optic.scala
inline def reverseGet(b: B): T

Build the "no context" reverse — takes a fresh B and produces the corresponding T. Available when the carrier has a ReverseAccessor[F] instance (today: Either and Direct).

Build the "no context" reverse — takes a fresh B and produces the corresponding T. Available when the carrier has a ReverseAccessor[F] instance (today: Either and Direct).

Attributes

Source
Optic.scala
inline def transfer[C](f: C => B): T => C => T

Overwrite a T-shaped value at the focus — available when the carrier can witness T => F[X, B] (e.g. Direct, where F[X, B] = B). transfer lifts a C => B into this same shape with an extra C argument.

Overwrite a T-shaped value at the focus — available when the carrier can witness T => F[X, B] (e.g. Direct, where F[X, B] = B). transfer lifts a C => B into this same shape with an extra C argument.

Attributes

Source
Optic.scala
inline def transform(f: D => B): T => T

Generalised place: transform a D at the focus via D => B rather than replacing unconditionally.

Generalised place: transform a D at the focus via D => B rather than replacing unconditionally.

Attributes

Source
Optic.scala

Instances

given innerProfunctor: [S, T, F[_, _]] => ForgetfulFunctor[F] => innerProfunctor[S, T, F]

Profunctor over (B, A)dimap on the inner focus pair. Requires a ForgetfulFunctor[F] so the carrier can map its focus in place.

Profunctor over (B, A)dimap on the inner focus pair. Requires a ForgetfulFunctor[F] so the carrier can map its focus in place.

Attributes

Source
Optic.scala
given outerProfunctor: [A, B, F[_, _]] => outerProfunctor[A, B, F]

Profunctor over (S, T)dimap on the outer parameter pair, letting callers pre-compose the source side and post-compose the result side of a fixed-focus optic.

Profunctor over (S, T)dimap on the outer parameter pair, letting callers pre-compose the source side and post-compose the result side of a fixed-focus optic.

Attributes

Source
Optic.scala

Constructors

def id[A]: BijectionIso[A, A, A, A]

The identity optic — S is its own focus and modification has no effect. Carrier is data.Direct (no leftover). Returns the concrete BijectionIso (not an anonymous Optic) so id.andThen(x) picks up the fused compose members like any other Iso.

The identity optic — S is its own focus and modification has no effect. Carrier is data.Direct (no leftover). Returns the concrete BijectionIso (not an anonymous Optic) so id.andThen(x) picks up the fused compose members like any other Iso.

Attributes

Source
Optic.scala

Extensions

Extensions

extension [S, T, A, B, F[_, _]](o: Optic[S, T, A, B, F])(using FT: ForgetfulTraverse[F, Applicative])
inline def all(s: S): List[F[o.X, A]]

Every visited focus, still inside its carrier (List[F[o.X, A]]) — the raw-optic counterpart of the carrier-free CanFold.foci.

Every visited focus, still inside its carrier (List[F[o.X, A]]) — the raw-optic counterpart of the carrier-free CanFold.foci.

Attributes

Source
Optic.scala
extension [S, T, A, B, F[_, _]](self: Optic[S, T, A, B, F])
inline def andThen[G[_, _], C, D](o: Optic[A, B, C, D, G])(using m: Morph[F, G]): Optic[S, T, C, D, m.Out]

Cross-carrier .andThen — picks the direction via a summoned compose.Morph when the two optics' carriers differ. With one exception (forget2multifocus / multifocus2forget), cats-eo ships no bidirectional Composer pairs, so at most one Morph applies per carrier pair. That one pair can make a Forget[F]MultiFocus[F] chain ambiguous; it's resolved via the explicit Composer[..].to(o) form (see multifocus2forget).

Cross-carrier .andThen — picks the direction via a summoned compose.Morph when the two optics' carriers differ. With one exception (forget2multifocus / multifocus2forget), cats-eo ships no bidirectional Composer pairs, so at most one Morph applies per carrier pair. That one pair can make a Forget[F]MultiFocus[F] chain ambiguous; it's resolved via the explicit Composer[..].to(o) form (see multifocus2forget).

Attributes

Example
lens[Person](_.phones)
 .andThen(Traversal.each[ArraySeq, Phone])
 .andThen(lens[Phone](_.isMobile))
Source
Optic.scala
def morph[G[_, _]](using cf: Composer[F, G]): Optic[S, T, A, B, G]

Re-express this optic over a different carrier G via the summoned Composer[F, G]. Ordinary code composes cross-carrier through andThen above (which morphs implicitly); the explicit form serves law / behaviour specs and the rare Morph-ambiguous chain.

Re-express this optic over a different carrier G via the summoned Composer[F, G]. Ordinary code composes cross-carrier through andThen above (which morphs implicitly); the explicit form serves law / behaviour specs and the rare Morph-ambiguous chain.

Attributes

Source
Optic.scala
extension [S, T, A, B, F[_, _]](self: Optic[S, T, A, B, F])(using ra: ReverseAccessor[F])
inline def andThen[D](o: Review[B, D]): Review[T, D]

ANY reversible outer ∘ build-only inner — only the two BUILD sides matter, so the composite collapses to a Review (reverseGet ∘ reverseGet), the build-direction mirror of the read-only andThen collapse.

ANY reversible outer ∘ build-only inner — only the two BUILD sides matter, so the composite collapses to a Review (reverseGet ∘ reverseGet), the build-direction mirror of the read-only andThen collapse.

Attributes

Source
Optic.scala
inline def andThen[G[_], D](o: Unfold[B, D, G]): Unfold[T, D, G]

ANY reversible outer ∘ build-only-many inner — the inner Unfold assembles the focus B from a layer F[D], and this optic's build half re-homes it to T, so the composite is an Unfold[T, D, F] (reverseGet ∘ embed). The many-rung mirror of the andThen(Review) overload above; fires for Iso / Prism outers (Review outers resolve to the fused Review.andThen member first).

ANY reversible outer ∘ build-only-many inner — the inner Unfold assembles the focus B from a layer F[D], and this optic's build half re-homes it to T, so the composite is an Unfold[T, D, F] (reverseGet ∘ embed). The many-rung mirror of the andThen(Review) overload above; fires for Iso / Prism outers (Review outers resolve to the fused Review.andThen member first).

Attributes

Source
Optic.scala
inline def writeOnly: Review[T, B]

The build half alone as a concrete Review — the write-direction dual of readOnly.

The build half alone as a concrete Review — the write-direction dual of readOnly.

Attributes

Source
Optic.scala
extension [S, T, A, B, F[_, _]](self: Optic[S, T, A, B, F])(using FF: ForgetfulFunctor[F])
inline def andThen[C, D](o: Modify[A, B, C, D]): Modify[S, T, C, D]

ANY writable outer ∘ write-only inner — the inner cannot be read, so the composite is write-only too: a Modify running modify(o.modify(f)).

ANY writable outer ∘ write-only inner — the inner cannot be read, so the composite is write-only too: a Modify running modify(o.modify(f)).

Attributes

Source
Optic.scala