Traversal

dev.constructive.eo.optics.Traversal
See theTraversal companion class
object 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, …).

'''Keyed access lives in Index / At — as constructor objects, not typeclasses.''' Index(i) / Index(k) focuses one positional or keyed slot (write on an absent slot passes through — no insert), At(k) is the total Map lens to Option[V] (Some upserts, None deletes), and Each is each under the Monocle-searched name. Each returns an ordinary optic that composes after .andThen like any other; a bespoke keyed Optional remains a one-liner when the container isn't a Seq/Map:

def index[K, V](k: K): Optional[Map[K, V], Map[K, V], V, V] =
 Optional[Map[K, V], Map[K, V], V, V](
   getOrModify = m => m.get(k).toRight(m),
   reverseGet = { case (m, v) => m.updated(k, v) },
 )

Known-arity focus sets go through two / three / four. A predicate-filtering WRITE optic (Monocle's deprecated filterIndex / lens-library filtered) is unlawful — a write can flip which elements the predicate selects, breaking composition laws — so it is not provided; filter on the read side instead (Fold.select / AffineFold.select / Optional.selectReadOnly).

Attributes

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

Members list

Grouped members

Constructors

def both[F[_, _], A, B](using BT: Bitraverse[F]): Traversal[F[A, A], F[B, B], A, B]

Bitraverse[F] at a single element type, both slots — every A position of an F[A, A] (Ior[A, A], (A, A), Validated[A, A]): fold or rewrite all of them in one pass.

Bitraverse[F] at a single element type, both slots — every A position of an F[A, A] (Ior[A, A], (A, A), Validated[A, A]): fold or rewrite all of them in one pass.

Attributes

Source
Traversal.scala
def each[T[_] : Traverse, A]: Traversal[T[A], T[A], A, A]

Monomorphic Traversal over Traverse[T]S = T = T[A], focus preserved.

Monomorphic Traversal over Traverse[T]S = T = T[A], focus preserved.

Attributes

Source
Traversal.scala
def first[F[_, _], A, B, C](using BT: Bitraverse[F]): Traversal[F[A, C], F[B, C], A, B]

Bitraverse[F] Traversal over the FIRST slot — the second slot rides along untouched (Either's left, Tuple2._1, Ior's left, Validated's invalid, …). Feeds pEach with a left-slot Traverse adapter over bitraverse / bifoldLeft / bifoldRight.

Bitraverse[F] Traversal over the FIRST slot — the second slot rides along untouched (Either's left, Tuple2._1, Ior's left, Validated's invalid, …). Feeds pEach with a left-slot Traverse adapter over bitraverse / bifoldLeft / bifoldRight.

Attributes

Source
Traversal.scala
def pEach[T[_] : Traverse, A, B]: Traversal[T[A], T[B], A, B]

Polymorphic counterpart to each — allows focus type change.

Polymorphic counterpart to each — allows focus type change.

Reassembly walks the original container with Functor.map plus a captured positional var — equivalent to Traverse.mapAccumulate but without the State thunk chain (the dominant CPU cost on profiled nested traversals). For ArraySeq the .from body bypasses Traverse[ArraySeq].map entirely (which threads through StrictOptimizedSeqOps → non-devirtualised SeqOps.size$, observed as 18% CPU), instead wrapping the focus vector directly via ArraySeq.unsafeWrapArray.

Attributes

Source
Traversal.scala
def second[F[_, _], A, B, C](using BT: Bitraverse[F]): Traversal[F[C, A], F[C, B], A, B]

first's twin over the SECOND slot (Either's right, Tuple2._2, …).

first's twin over the SECOND slot (Either's right, Tuple2._2, …).

Attributes

Source
Traversal.scala
def selfChildren[S](children: S => PSVec[S], rebuild: (S, PSVec[S]) => S): Traversal[S, S, S, S]

Monomorphic self-traversal from an explicit immediate-children view — focuses the values of S that are themselves S (the immediate sub-terms), with S itself as the leftover skeleton. children(s) is the immediate children as a focus vector; rebuild(s, vec) reassembles s with that same number of children swapped in (same order). The two must agree on arity and order: rebuild(s, children(s)) == s.

Monomorphic self-traversal from an explicit immediate-children view — focuses the values of S that are themselves S (the immediate sub-terms), with S itself as the leftover skeleton. children(s) is the immediate children as a focus vector; rebuild(s, vec) reassembles s with that same number of children swapped in (same order). The two must agree on arity and order: rebuild(s, children(s)) == s.

PSVec-native: to / from pass the PSVec straight through, so both the read path (Plated.children / universe, which read to(s)._2) and the write path (Plated.transform / rewrite, which traverse and rebuild through the carrier) avoid any ListPSVec conversion. This is the carrier behind Plated — a recursive ADT's plate. Unlike each / pEach there is no container T[_]; the children of a node are gathered case-by-case, and the variable arity across cases (a binary node has two children, a leaf none) is exactly the PSVec shape.

Attributes

Source
Traversal.scala
inline def two[S, T, A, B](inline a: S => A, inline b: S => A, inline reverse: (B, B) => T): Traversal[S, T, A, B]

Traversal over two per-element getters with a reverse reassembly. The arity is known at construction time, so the foci tabulate straight into the MultiFocus[PSVec] carrier and the result composes like any other traversal — past each, a Lens, a Prism, or another fixed-arity hop. reverse sees only the (modified) foci: the constructor is full-cover, so any leftover context of S must be rebuilt by reverse itself (drill with a Lens first when there are sibling fields). For the Grate-shaped Int => A encoding, see MultiFocus.tuple.

Traversal over two per-element getters with a reverse reassembly. The arity is known at construction time, so the foci tabulate straight into the MultiFocus[PSVec] carrier and the result composes like any other traversal — past each, a Lens, a Prism, or another fixed-arity hop. reverse sees only the (modified) foci: the constructor is full-cover, so any leftover context of S must be rebuilt by reverse itself (drill with a Lens first when there are sibling fields). For the Grate-shaped Int => A encoding, see MultiFocus.tuple.

The tabulating subclass is macro-generated per CALL SITE (see TraversalArityMacro): each site keeps its own monomorphic to / from bodies, and literal selector / reverse lambdas are beta-reduced straight into the tabulation.

Attributes

Source
Traversal.scala

Value members

Concrete methods

inline def four[S, T, A, B](inline a: S => A, inline b: S => A, inline c: S => A, inline d: S => A, inline reverse: (B, B, B, B) => T): Traversal[S, T, A, B]

Fixed-arity-4 — see two. @group Constructors

Fixed-arity-4 — see two. @group Constructors

Attributes

Source
Traversal.scala
inline def three[S, T, A, B](inline a: S => A, inline b: S => A, inline c: S => A, inline reverse: (B, B, B) => T): Traversal[S, T, A, B]

Fixed-arity-3 — see two. @group Constructors

Fixed-arity-3 — see two. @group Constructors

Attributes

Source
Traversal.scala