MultiFocus

dev.constructive.eo.data.MultiFocus$package.MultiFocus
object MultiFocus

API façade under the carrier's public name. The instances live in MultiFocusK (the opaque anchor's companion, where implicit scope finds them); this re-export keeps MultiFocus.apply / MultiFocus.fromLensF call-shapes and legacy import data.MultiFocus.given working.

Attributes

Source
MultiFocus.scala
Graph
Supertypes
class Object
trait Matchable
class Any
Self type
MultiFocus.type

Members list

Grouped members

Instances

Exported from MultiFocusK

Optional → MultiFocus[F] — mirror of either2multifocus over the Affine miss / hit split.

Optional → MultiFocus[F] — mirror of either2multifocus over the Affine miss / hit split.

Attributes

Source
MultiFocus.scala
Exported from MultiFocusK

Prism → MultiFocus[F] — hit becomes a pure singleton, miss becomes Alternative[F].empty.

Prism → MultiFocus[F] — hit becomes a pure singleton, miss becomes Alternative[F].empty.

Attributes

Source
MultiFocus.scala
export forget2multifocus: [F[_]]
Exported from MultiFocusK

Forget[F] ↪ MultiFocus[F] — a Fold slots into the pair carrier with X = Unit.

Forget[F] ↪ MultiFocus[F] — a Fold slots into the pair carrier with X = Unit.

Attributes

Source
MultiFocus.scala
Exported from MultiFocusK

Iso → MultiFocus[F]. Requires Applicative[F] to broadcast the Iso's plain A focus into a singleton F[A]; the write-back picks the singleton out (throws on cardinality ≠ 1).

Iso → MultiFocus[F]. Requires Applicative[F] to broadcast the Iso's plain A focus into a singleton F[A]; the write-back picks the singleton out (throws on cardinality ≠ 1).

Attributes

Source
MultiFocus.scala
Exported from MultiFocusK

Iso ↪ MultiFocus[Function1[X0, *]] — the Iso side of the grate-shaped surface. Iso's forward to: S => A is broadcast to the constant rebuild _ => a; the reverse reads the rebuild at any X0 (null sentinel — sound because no shipped rebuild observes its argument; see the fixedtraversal-fold spike doc).

Iso ↪ MultiFocus[Function1[X0, *]] — the Iso side of the grate-shaped surface. Iso's forward to: S => A is broadcast to the constant rebuild _ => a; the reverse reads the rebuild at any X0 (null sentinel — sound because no shipped rebuild observes its argument; see the fixedtraversal-fold spike doc).

Attributes

Source
MultiFocus.scala
export mfAssoc: [F[_] : Traverse : MultiFocusFromList, Xo, Xi]
Exported from MultiFocusK

Same-carrier composition for MultiFocus[F]traversal.andThen(traversal), F-parametric. Z = (Xo, F[(Xi, Int)]): the outer leftover plus, per outer focus, the inner leftover and its focus count, so composeFrom can carve the flat modified vector back into per-element slices (cursor over an array snapshot). Inners that mix in MultiFocusSingleton (the Lens bridge) take an always-hit fast path that skips the per-element inner fold. Flat focus order is the outer's traversal order, inner order within each element.

Same-carrier composition for MultiFocus[F]traversal.andThen(traversal), F-parametric. Z = (Xo, F[(Xi, Int)]): the outer leftover plus, per outer focus, the inner leftover and its focus count, so composeFrom can carve the flat modified vector back into per-element slices (cursor over an array snapshot). Inners that mix in MultiFocusSingleton (the Lens bridge) take an always-hit fast path that skips the per-element inner fold. Flat focus order is the outer's traversal order, inner order within each element.

Attributes

Source
MultiFocus.scala
export mfAssocFunction1: [X0, Xo, Xi]
Exported from MultiFocusK

Function1-shaped same-carrier composition — the grate-absorbed case. The general mfAssoc requires Traverse[F] + MultiFocusFromList[F]; Function1[X0, *] admits neither, so this instance composes the rebuild closures directly. The outer rebuild is a constant broadcast — sound because every shipped outer (iso-morphed, tuple-built) rebuilds via broadcast anyway. See docs/research/2026-04-29-fixedtraversal-fold-spike.md.

Function1-shaped same-carrier composition — the grate-absorbed case. The general mfAssoc requires Traverse[F] + MultiFocusFromList[F]; Function1[X0, *] admits neither, so this instance composes the rebuild closures directly. The outer rebuild is a constant broadcast — sound because every shipped outer (iso-morphed, tuple-built) rebuilds via broadcast anyway. See docs/research/2026-04-29-fixedtraversal-fold-spike.md.

Attributes

Source
MultiFocus.scala
export mfAssocPSVec: [Xo, Xi]
Exported from MultiFocusK

PSVec-specialised same-carrier composition. Where the generic mfAssoc body builds two intermediate List accumulators + materialises via fromList, this body writes directly into IntArrBuilder / ObjArrBuilder and stores the existential as parallel arrays in AssocSndZ, sidestepping the per-element (Xi, Int) Tuple2 the generic path pays. Fast paths for MultiFocusSingleton (always-hit, Lens bridge) and MultiFocusPSMaybeHit (Prism / Optional bridges) inners; reassembly hands each inner an O(1) PSVec.slice view. See docs/research/2026-04-29-powerseries-fold-spike.md.

PSVec-specialised same-carrier composition. Where the generic mfAssoc body builds two intermediate List accumulators + materialises via fromList, this body writes directly into IntArrBuilder / ObjArrBuilder and stores the existential as parallel arrays in AssocSndZ, sidestepping the per-element (Xi, Int) Tuple2 the generic path pays. Fast paths for MultiFocusSingleton (always-hit, Lens bridge) and MultiFocusPSMaybeHit (Prism / Optional bridges) inners; reassembly hands each inner an O(1) PSVec.slice view. See docs/research/2026-04-29-powerseries-fold-spike.md.

Attributes

Source
MultiFocus.scala
export mfFold: [F[_] : Foldable]
Exported from MultiFocusK

ForgetfulFold[MultiFocus[F]] via Foldable[F] — folds the focus vector, discarding the leftover. Unlocks .foldMap / .headOption / .length / .exists.

ForgetfulFold[MultiFocus[F]] via Foldable[F] — folds the focus vector, discarding the leftover. Unlocks .foldMap / .headOption / .length / .exists.

Attributes

Source
MultiFocus.scala
export mfFunctor: [F[_] : Functor]
Exported from MultiFocusK

ForgetfulFunctor[MultiFocus[F]] via Functor[F] — maps every focus, leftover untouched. Unlocks .modify / .replace on Traversal-family optics.

ForgetfulFunctor[MultiFocus[F]] via Functor[F] — maps every focus, leftover untouched. Unlocks .modify / .replace on Traversal-family optics.

Attributes

Source
MultiFocus.scala
export mfTraverse: [F[_] : Traverse]
Exported from MultiFocusK

ForgetfulTraverse[MultiFocus[F], Applicative] via Traverse[F] — effectful rewrite of every focus in F's traversal order. Unlocks .modifyA / .all.

ForgetfulTraverse[MultiFocus[F], Applicative] via Traverse[F] — effectful rewrite of every focus in F's traversal order. Unlocks .modifyA / .all.

Attributes

Source
MultiFocus.scala
export multifocus2forget: [F[_]]
Exported from MultiFocusK

MultiFocus[F] ↪ Forget[F] — read-only escape: discard the structural leftover, keep the focused F[A]. An explicit carrier morph alongside the carrier-wide Optic.foldMap / .headOption / .length / .exists extension methods.

MultiFocus[F] ↪ Forget[F] — read-only escape: discard the structural leftover, keep the focused F[A]. An explicit carrier morph alongside the carrier-wide Optic.foldMap / .headOption / .length / .exists extension methods.

Structurally this is the inverse of forget2multifocus — both Composer directions ship. That's normally banned by the cats-eo Morph resolution invariant (a bidirectional pair makes Morph[Forget[F], MultiFocus[F]] ambiguous because both leftToRight and rightToLeft fire). The Composer ships anyway because:

  1. The from side requires T = Unit (Forget loses the leftover, so it can't reconstruct a T ≠ Unit). Only T-Unit MultiFocus optics qualify, which the type system enforces at use sites.
  2. Any chain-resolution ambiguity surfaces at forget.andThen(multifocus) / multifocus.andThen(fold) call sites — the user resolves by routing through the explicit Composer[..].to(o) form rather than .andThen.

Practical Morph fallout: if a user actually hits the ambiguity, they get a clear implicit-not- found message naming both Composers; the workaround is one extra .morph-shaped call.

Attributes

Source
MultiFocus.scala
export multifocus2modify: [F[_] : Functor]
Exported from MultiFocusK

MultiFocus[F] → ModifyF. Uniform Modify widening for any Functor[F].

MultiFocus[F] → ModifyF. Uniform Modify widening for any Functor[F].

Attributes

Source
MultiFocus.scala
Exported from MultiFocusK

Lens → MultiFocus[F]. Mixes in MultiFocusSingleton so the mfAssoc fast-path fires.

Lens → MultiFocus[F]. Mixes in MultiFocusSingleton so the mfAssoc fast-path fires.

Attributes

Source
MultiFocus.scala

Constructors

def apply[F[_], A]: Optic[F[A], F[A], A, A, MultiFocus[F]]
Exported from MultiFocusK

Generic factory: X = F[A], focus = fa, rebuild = identity.

Generic factory: X = F[A], focus = fa, rebuild = identity.

Attributes

Source
MultiFocus.scala
def fromLensF[F[_], S, T, A, B](lens: Optic[S, T, F[A], F[B], Tuple2]): Optic[S, T, A, B, MultiFocus[F]]
Exported from MultiFocusK

Reinterpret a Lens whose focus is already an F[A] as a MultiFocus optic over the elements — the container the Lens reads IS the focus vector; X and the rebuild pass straight through.

Reinterpret a Lens whose focus is already an F[A] as a MultiFocus optic over the elements — the container the Lens reads IS the focus vector; X and the rebuild pass straight through.

Attributes

Source
MultiFocus.scala
def pApply[F[_], A, B]: Optic[F[A], F[B], A, B, MultiFocus[F]]
Exported from MultiFocusK

Polymorphic counterpart to apply — allows focus type change (F[A] => F[B]), the Traversal.pEach analogue at the generic factory. Sound for the same reason: the rebuild is identity on the written-back F[B], so no B ever has to fit an A-shaped hole. This is what un-pins the collect flavours' element type — pApply[F, A, Row].collectWith(...) emits a different row type than it read.

Polymorphic counterpart to apply — allows focus type change (F[A] => F[B]), the Traversal.pEach analogue at the generic factory. Sound for the same reason: the rebuild is identity on the written-back F[B], so no B ever has to fit an A-shaped hole. This is what un-pins the collect flavours' element type — pApply[F, A, Row].collectWith(...) emits a different row type than it read.

Attributes

Source
MultiFocus.scala
def representable[F[_], A](using F: Representable[F]): Optic[F[A], F[A], A, A, MultiFocus[[_] =>> F.Representation => _$37]]
Exported from MultiFocusK

Generic Function1-shaped factory — any Representable[F] container yields a MultiFocus[Function1[F.Representation, *]]-carrier optic over F[A] with focus A. Encoding: X = Unit, rebuild = F.Representation => A. On to(fa) snapshot F.index(fa); on from((_, k)) materialise via F.tabulate(k). The .modify(f) round-trip is exactly F.map(fa)(f).

Generic Function1-shaped factory — any Representable[F] container yields a MultiFocus[Function1[F.Representation, *]]-carrier optic over F[A] with focus A. Encoding: X = Unit, rebuild = F.Representation => A. On to(fa) snapshot F.index(fa); on from((_, k)) materialise via F.tabulate(k). The .modify(f) round-trip is exactly F.map(fa)(f).

Attributes

Source
MultiFocus.scala
def tuple[T <: Tuple, A](using sz: ValueOf[Size[T]], ev: Union[T] <:< A): Optic[T, T, A, A, MultiFocus[[_] =>> Int => _$42]]
Exported from MultiFocusK

Polymorphic homogeneous-tuple Function1-shaped factory. to(t) = ((), i => t._i), from((_, k)) materialises via Tuple.fromArray(Array.tabulate(size)(i => k(i))).

Polymorphic homogeneous-tuple Function1-shaped factory. to(t) = ((), i => t._i), from((_, k)) materialises via Tuple.fromArray(Array.tabulate(size)(i => k(i))).

Attributes

Example
 val g3 = MultiFocus.tuple[(Int, Int, Int), Int]
 g3.modify(_ + 1)((1, 2, 3))   // (2, 3, 4)
 g3.replace(42)((1, 2, 3))     // (42, 42, 42)
Source
MultiFocus.scala

Value members

Concrete methods

transparent inline def apply[F[_], X, A](x: X, fa: F[A]): MultiFocusK[F, X, A]

Pair a leftover x with a focus vector fa as the carrier value. Identity at runtime (the opaque type erases to the pair); the unwrap boundary is MultiFocusK.context / MultiFocusK.foci.

Pair a leftover x with a focus vector fa as the carrier value. Identity at runtime (the opaque type erases to the pair); the unwrap boundary is MultiFocusK.context / MultiFocusK.foci.

Attributes

Source
MultiFocus.scala

Exports

Defined exports

final type AssocSndZ = AssocSndZ
Exported from MultiFocusK$

Attributes

Source
MultiFocus.scala
Exported from MultiFocusK

Attributes

Source
MultiFocus.scala
Exported from MultiFocusK

Attributes

Source
MultiFocus.scala
Exported from MultiFocusK

Attributes

Source
MultiFocus.scala