MultiFocusK
Attributes
- Source
- MultiFocus.scala
- Graph
-
- Supertypes
-
class Objecttrait Matchableclass Any
- Self type
-
MultiFocusK.type
Members list
Grouped members
Instances
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
Optional → MultiFocus[PSVec]. Mixes in MultiFocusPSMaybeHit so mfAssocPSVec skips the per-element Affine[o.X, Unit] wrapper the generic path would build.
Optional → MultiFocus[PSVec]. Mixes in MultiFocusPSMaybeHit so mfAssocPSVec skips the per-element Affine[o.X, Unit] wrapper the generic path would build.
Attributes
- Source
- MultiFocus.scala
Optional → MultiFocus[PSVec]. Mixes in MultiFocusPSMaybeHit so mfAssocPSVec skips the per-element Affine[o.X, Unit] wrapper the generic path would build.
Optional → MultiFocus[PSVec]. Mixes in MultiFocusPSMaybeHit so mfAssocPSVec skips the per-element Affine[o.X, Unit] wrapper the generic path would build.
Attributes
- Source
- MultiFocus.scala
- Supertypes
- Self type
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
Prism → MultiFocus[PSVec] — lifts a Prism-carrier optic so prism.andThen(traversal) type-checks. Mixes in MultiFocusPSMaybeHit so the PSVec-specialised mfAssocPSVec body skips the per-element Either[o.X, Unit] wrapper the generic to path would build.
Prism → MultiFocus[PSVec] — lifts a Prism-carrier optic so prism.andThen(traversal) type-checks. Mixes in MultiFocusPSMaybeHit so the PSVec-specialised mfAssocPSVec body skips the per-element Either[o.X, Unit] wrapper the generic to path would build.
Attributes
- Source
- MultiFocus.scala
Prism → MultiFocus[PSVec] — lifts a Prism-carrier optic so prism.andThen(traversal) type-checks. Mixes in MultiFocusPSMaybeHit so the PSVec-specialised mfAssocPSVec body skips the per-element Either[o.X, Unit] wrapper the generic to path would build.
Prism → MultiFocus[PSVec] — lifts a Prism-carrier optic so prism.andThen(traversal) type-checks. Mixes in MultiFocusPSMaybeHit so the PSVec-specialised mfAssocPSVec body skips the per-element Either[o.X, Unit] wrapper the generic to path would build.
Attributes
- Source
- MultiFocus.scala
- Supertypes
- Self type
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
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
Iso ↪ MultiFocus[Function1[X0, *]] — the Iso side of the grate-shaped surface. Iso's forward to: S => A is broadcast to every index, so the bundle it produces is index-free (broadcast) and a composite reading through it never has to sample an index.
Iso ↪ MultiFocus[Function1[X0, *]] — the Iso side of the grate-shaped surface. Iso's forward to: S => A is broadcast to every index, so the bundle it produces is index-free (broadcast) and a composite reading through it never has to sample an index.
The product is a Function1BroadcastOptic — a class because the optic is the one thing the carrier's sum cannot describe before a read: a broadcast optic builds exactly one value per position, so mfAssocFunction1 writes it through the class's own hook (Function1BroadcastOptic.broadcastFrom) rather than through a bundle read it did not build. The class also owns the one read of a bundle it did not build: an index-free bundle is read outright, and a tabulating one at the real index the RepresentativeIndex witness supplies — a defined answer, never a forged sentinel, and never a value the index types the Grate factories fix (Int, Boolean, Unit, singletons) have to supply themselves.
The using clause is the cost side of that contract, exactly as on main: index types with a canonical value resolve import-free off RepresentativeIndex; anything else is refused rather than guessed — no index is ever forged, and nothing else needs a stand-in either.
Attributes
- Source
- MultiFocus.scala
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
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
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
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
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
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:
- The
fromside requiresT = Unit(Forget loses the leftover, so it can't reconstruct a T ≠ Unit). Only T-UnitMultiFocus optics qualify, which the type system enforces at use sites. - Any chain-resolution ambiguity surfaces at
forget.andThen(multifocus)/multifocus.andThen(fold)call sites — the user resolves by routing through the explicitComposer[..].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
MultiFocus[F] → ModifyF. Uniform Modify widening for any Functor[F].
MultiFocus[F] → ModifyF. Uniform Modify widening for any Functor[F].
Attributes
- Source
- MultiFocus.scala
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
Lens → MultiFocus[PSVec]. GetReplaceLens fast-path elides the (s, get(s)) Tuple2 the generic body would build. The to body builds anonymous Optic values inline so MultiFocusSingleton can refer to o.X without tripping Scala 3's "class parent cannot refer to constructor parameters" rule.
Lens → MultiFocus[PSVec]. GetReplaceLens fast-path elides the (s, get(s)) Tuple2 the generic body would build. The to body builds anonymous Optic values inline so MultiFocusSingleton can refer to o.X without tripping Scala 3's "class parent cannot refer to constructor parameters" rule.
Attributes
- Source
- MultiFocus.scala
Lens → MultiFocus[PSVec]. GetReplaceLens fast-path elides the (s, get(s)) Tuple2 the generic body would build. The to body builds anonymous Optic values inline so MultiFocusSingleton can refer to o.X without tripping Scala 3's "class parent cannot refer to constructor parameters" rule.
Lens → MultiFocus[PSVec]. GetReplaceLens fast-path elides the (s, get(s)) Tuple2 the generic body would build. The to body builds anonymous Optic values inline so MultiFocusSingleton can refer to o.X without tripping Scala 3's "class parent cannot refer to constructor parameters" rule.
Attributes
- Source
- MultiFocus.scala
- Supertypes
- Self type
Constructors
Generic factory: X = F[A], focus = fa, rebuild = identity.
Construct an index-free (broadcast) bundle on the Function1[X0, *]-shaped carrier: a is the focus at every index, and it is known without consulting one. The mirror of MultiFocusK.foci (F[A]-shaped consumers) for consumers that need the value itself.
Construct an index-free (broadcast) bundle on the Function1[X0, *]-shaped carrier: a is the focus at every index, and it is known without consulting one. The mirror of MultiFocusK.foci (F[A]-shaped consumers) for consumers that need the value itself.
Use it when an optic's source has no X0-index of its own — an Iso reshaped into this carrier (forgetful2multifocusFunction1), or any optic that broadcasts one focus across the index set. Compositions read the difference: an index-free outer is read once (not per index), and the write of a composite whose read was index-free stays index-free all the way out.
Attributes
- Source
- MultiFocus.scala
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
Reinterpret an Optional whose focus is an F[A] as a MultiFocus optic over the elements — the mirror of fromPrismF over the Affine miss / hit split (miss recycled covariantly, both directions).
Reinterpret an Optional whose focus is an F[A] as a MultiFocus optic over the elements — the mirror of fromPrismF over the Affine miss / hit split (miss recycled covariantly, both directions).
Attributes
- Source
- MultiFocus.scala
Reinterpret a Prism whose focus is an F[A] as a MultiFocus optic over the elements — the miss branch surfaces as MonoidK[F].empty (zero foci) and passes the leftover back through the prism's build path on write.
Reinterpret a Prism whose focus is an F[A] as a MultiFocus optic over the elements — the miss branch surfaces as MonoidK[F].empty (zero foci) and passes the leftover back through the prism's build path on write.
Attributes
- Source
- MultiFocus.scala
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
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).
Position is a read-time argument, never a property of the optic: the index is supplied per call by the .at(i) extension (g.at(i)(fa) == F.index(fa)(i)), and Representable has no canonical Representation to hand a constructor anyway — Function1[Boolean, *] has no privileged Boolean, and Function1[Nothing, *] has no index at all. So this factory takes no representative index, and the built optic carries none: X = Unit, and the whole index-parametric read lives in the focus bundle. (Pre-0.19 a second name, representableAt(F)(repr0), took exactly such an index; it built this same optic — see the changelog for the removal.)
Attributes
- Source
- MultiFocus.scala
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
Pointwise ZIP of two containers — a Grate's reason for existing, and the one operation representable made possible but never exposed.
Pointwise ZIP of two containers — a Grate's reason for existing, and the one operation representable made possible but never exposed.
A Grate is ((F[A] => A) => B) => F[B]: unlike a Traversal it can see EVERY focus at once while rebuilding, which is exactly what combining two structures needs. Traversal cannot express this — it visits one focus at a time with no access to a second structure — and neither can modify. Here the shape is concrete: read both containers as index functions and tabulate their pointwise combination.
Lawful for any Representable[F] (no shape to mismatch — every representation point exists in both), and zipWith(fa, fa)(f) == F.map(fa)(a => f(a, a)).
Attributes
- Example
-
// Two configurations merged field-by-field: val merged = MultiFocus.zipWith(defaults, overrides)((d, o) => o.orElse(d)) - Source
- MultiFocus.scala
Type members
Types
The grate-shaped carrier as a plain type constructor: MultiFocus[Function1[X0, *]]. Spelled without the type lambda where a signature has to match an eta-expanded carrier (an override of a member generic in F), and handy for writing one's own Function1-carried optics.
The grate-shaped carrier as a plain type constructor: MultiFocus[Function1[X0, *]]. Spelled without the type lambda where a signature has to match an eta-expanded carrier (an override of a member generic in F), and handy for writing one's own Function1-carried optics.
Attributes
- Source
- MultiFocus.scala
Givens
Givens
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.
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 two sides of a composed optic need not have the same shape, and the carrier says which is which per bundle (see MultiFocusK.Focus), so the kernel branches on data rather than on the optic's class — which also means a composite (an anonymous Optic) keeps reporting its true shape to the next composition up:
- read — an index-free outer (
Broadcasthalf) is read ONCE and its value handed to the inner (inner.to(a)), so the composite inherits the inner's shape. A tabulating outer is read per index:i => inner.to(readO(i))read ati. Both are exact; neither invents an index. - write — the composite's write shape follows the read shape, recorded in AssocF1Z. An index-free outer collapses the written bundle once (
inner.from(bundle)— exact whenever the incoming bundle is itself broadcast, which every shipped.modify/.replace/.collectWithpipeline produces) and hands the outer aBroadcasthalf, so the outer's rebuild needs no index. A tabulating outer writes each position its own value, sotuple.andThen().modify(f)reaches every slot with its ownf.
No write here needs a stand-in value: every inner is handed the leftover its own read produced and, when it has one, the index its bridge was constructed with.
Two tabulating sides (MultiFocus.tuple ∘ MultiFocus.tuple) are the one composition whose read is not a bijection: the composite reads one position per index (the diagonal), so the off-diagonal of each inner structure is not in the composite's focus vector. The plain composeFrom can only be lossy there (no C => D exists to put C values back into a D bundle); when the inner optic carries Optic.SameFocus — the witness Optic.andThen mixes into every composite from that call site's C =:= D, and the monomorphic factories mix in themselves — this kernel puts every position back where it was read, which is exactly the inverse of that diagonal read.
Attributes
- Source
- MultiFocus.scala
Extensions
Extensions
Singleton / cartesian aggregation, List-specific — collapses the whole focus list to ONE aggregated element: the result list has length 1 regardless of the focus count. Shape-changing, which is exactly what no Functor-based combinator can express; the length-preserving alternatives are collectMap / collectWith.
Singleton / cartesian aggregation, List-specific — collapses the whole focus list to ONE aggregated element: the result list has length 1 regardless of the focus count. Shape-changing, which is exactly what no Functor-based combinator can express; the length-preserving alternatives are collectMap / collectWith.
Attributes
- Source
- MultiFocus.scala
Functor-broadcast aggregation — preserves F-shape via map(_ => agg(fa)); every focus position receives the aggregate. Works for any Functor[F]; for List this is the ZipList-style length-preserving aggregation (use collectList for the shape-collapsing List-singleton semantics). For the generic apply factory (X = F[A], rebuild = identity), .collectMap is s => s.map(_ => agg(s)) — semantically Functor.map over the source.
Functor-broadcast aggregation — preserves F-shape via map(_ => agg(fa)); every focus position receives the aggregate. Works for any Functor[F]; for List this is the ZipList-style length-preserving aggregation (use collectList for the shape-collapsing List-singleton semantics). For the generic apply factory (X = F[A], rebuild = identity), .collectMap is s => s.map(_ => agg(s)) — semantically Functor.map over the source.
Attributes
- Source
- MultiFocus.scala
The algebraic-lens universal for the map-shaped collects — agg sees the whole focus collection ONCE, returns the per-focus rewrite, and that rewrite is mapped back over every position: fa.map(a => agg(fa)(a)). The currying is load-bearing: compute the batch summary in agg(fa), and the returned A => B runs per position without recomputing it.
The algebraic-lens universal for the map-shaped collects — agg sees the whole focus collection ONCE, returns the per-focus rewrite, and that rewrite is mapped back over every position: fa.map(a => agg(fa)(a)). The currying is load-bearing: compute the batch summary in agg(fa), and the returned A => B runs per position without recomputing it.
Subsumes both map-shaped siblings — collectMap(agg) = collectWith(fa => _ => agg(fa)) (constant per-focus function) and modify(f) = collectWith(_ => f) (aggregate ignored); pinned as laws MF4 / MF5. The shape-collapsing collectList is NOT expressible here: it changes the focus count, which no Functor-based combinator can. Requires only Functor[F], like collectMap.
Attributes
- Source
- MultiFocus.scala
Read the focus at a representative position. Requires Representable[F]. For MultiFocus[Function1[X0, *]], this is index(fa)(i) = fa(i).
Read the focus at a representative position. Requires Representable[F]. For MultiFocus[Function1[X0, *]], this is index(fa)(i) = fa(i).
Attributes
- Source
- MultiFocus.scala
The index-independent focus value, when this bundle has one: Some(a) for a Broadcast bundle, None for a genuine tabulation. The accessor that makes constancy observable — callers that need "the focus, whichever index" can ask here instead of inventing one.
The index-independent focus value, when this bundle has one: Some(a) for a Broadcast bundle, None for a genuine tabulation. The accessor that makes constancy observable — callers that need "the focus, whichever index" can ask here instead of inventing one.
Attributes
- Source
- MultiFocus.scala
The structural leftover. Identity at runtime.
The focus vector — the carrier's own F[A] view of the focus half. Identity at runtime for a tabulation; for a Broadcast it returns the index-free value's lifted F[A], so every consumer keeps working without an index.
The focus vector — the carrier's own F[A] view of the focus half. Identity at runtime for a tabulation; for a Broadcast it returns the index-free value's lifted F[A], so every consumer keeps working without an index.
Attributes
- Source
- MultiFocus.scala