Plated

dev.constructive.eo.optics.Plated
See thePlated companion trait
object Plated

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

Members list

Value members

Concrete methods

def apply[S](using p: Plated[S]): Plated[S]

Summon the instance.

Summon the instance.

Attributes

Source
Plated.scala
def children[S](s: S)(using P: Plated[S]): List[S]

The immediate sub-terms of s (one level down). Reads the plate's children vector directly.

The immediate sub-terms of s (one level down). Reads the plate's children vector directly.

Attributes

Source
Plated.scala
def everywhere[S](using P: Plated[S]): Optic[S, S, S, S, ModifyF]

The whole structure as a composable optic that reaches every sub-term — transform in optic form. everywhere.modify(h) == transform(h), so composing a downstream optic and modifying rewrites that focus at every depth, bottom-up:

The whole structure as a composable optic that reaches every sub-term — transform in optic form. everywhere.modify(h) == transform(h), so composing a downstream optic and modifying rewrites that focus at every depth, bottom-up:

// uppercase EVERY variable anywhere in the tree:
everywhere[Expr].andThen(varPrism).andThen(nameLens).modify(_.toUpperCase)(tree)

It is a write-side optic (a Modify whose modify is the recursive transform); it composes as the outer of .andThen with any inner optic that bridges into ModifyF (Lens / Prism / Optional / …), and the composite is transform(inner.modify(_)) by the optic composition law. For the read side — every sub-term as a list — use universe.

Attributes

Source
Plated.scala
def fromChildren[S](children: S => List[S], rebuild: (S, List[S]) => S): Plated[S]

Build a Plated from a List-shaped children view — the ergonomic hand-writing entry point ({ case Node(l, r) => List(l, r); … }). Wraps the List into the PSVec-native fromChildrenVec; fine for hand-written plates, while the performance-critical derived instances avoid the wrap.

Build a Plated from a List-shaped children view — the ergonomic hand-writing entry point ({ case Node(l, r) => List(l, r); … }). Wraps the List into the PSVec-native fromChildrenVec; fine for hand-written plates, while the performance-critical derived instances avoid the wrap.

Attributes

Source
Plated.scala

Build a Plated from an explicit children focus-vector view — the PSVec-native primitive. children(s) is the immediate sub-terms as a PSVec; rebuild(s, vec) reassembles s with that many children swapped in, same order. This is what generics.plate[S] emits, and it pays zero List conversion on either the read or the write path.

Build a Plated from an explicit children focus-vector view — the PSVec-native primitive. children(s) is the immediate sub-terms as a PSVec; rebuild(s, vec) reassembles s with that many children swapped in, same order. This is what generics.plate[S] emits, and it pays zero List conversion on either the read or the write path.

Attributes

Source
Plated.scala
def rewrite[S](f: S => Option[S])(s: S)(using P: Plated[S]): S

Apply the rule everywhere, bottom-up, and keep re-firing on each rewritten sub-term until the rule returns None at every node — Haskell lens's rewrite. The caller owns termination (a rule that always fires loops forever).

Apply the rule everywhere, bottom-up, and keep re-firing on each rewritten sub-term until the rule returns None at every node — Haskell lens's rewrite. The caller owns termination (a rule that always fires loops forever).

Trampolined through cats.Eval, so it is '''fully stack-safe on both axes''': the bottom-up descent over a deep tree (a 100k-deep spine is fine) '''and''' the fixpoint re-firing — a rule that fires in a long chain at one position (e.g. Counter(n) => Counter(n-1) repeated many times) bounces through the heap, not the call stack, so it won't overflow either. (This is why rewrite keeps the Eval trampoline rather than reusing transform's synchronous call-stack/heap-machine the way everywhere does — sharing it would put the re-fire chain back on the JVM call stack.)

Attributes

Source
Plated.scala
def transform[S](f: S => S)(root: S)(using P: Plated[S]): S

Bottom-up rewrite: rewrite every node's children first, then apply f to the node. The single pass each lens user reaches for.

Bottom-up rewrite: rewrite every node's children first, then apply f to the node. The single pass each lens user reaches for.

Hybrid for speed without giving up stack-safety: it recurses on the JVM call stack (≈ a hand-written recursive rebuild — no per-node heap Frame) while the depth stays under transformRecursionLimit, and hands any deeper subtree to transformMachine — an explicit heap-stack post-order walk — so a degenerate spine of any depth (100k+) still can't overflow. Both paths read children via Plated.childrenVec and rebuild via Plated.rebuild (no carrier tuple per node), and apply f in place at leaves — the f(s) shortcut (rather than f(rebuild(s, empty))) matches the non-leaf path because rebuild(leaf, empty) == leaf, the plateModifyIdentity law.

Attributes

Source
Plated.scala
def universe[S](s: S)(using P: Plated[S]): List[S]

Every sub-term of s, s itself first, in pre-order. Stack-safe via an explicit worklist; children are pushed straight off the PSVec (no per-node List).

Every sub-term of s, s itself first, in pre-order. Stack-safe via an explicit worklist; children are pushed straight off the PSVec (no per-node List).

Attributes

Source
Plated.scala

Extensions

Extensions

extension [S](self: Optic[S, S, S, S, MultiFocus[PSVec]])
def asPlated: Plated[S]

Wrap this self-traversal as a Plated instance (carrier-default childrenVec / rebuild; a derived / Plated.fromChildrenVec instance is cheaper — see Plated.rebuild).

Wrap this self-traversal as a Plated instance (carrier-default childrenVec / rebuild; a derived / Plated.fromChildrenVec instance is cheaper — see Plated.rebuild).

Attributes

Source
Plated.scala
def childrenOf(s: S): List[S]

Plated.children over this optic — the immediate sub-terms.

Plated.children over this optic — the immediate sub-terms.

Attributes

Source
Plated.scala
def rewriteAll(f: S => Option[S])(s: S): S

Plated.rewrite over this optic — bottom-up rewrite to a fixpoint.

Plated.rewrite over this optic — bottom-up rewrite to a fixpoint.

Attributes

Source
Plated.scala
def transformAll(f: S => S)(s: S): S

Plated.transform over this optic — bottom-up rewrite of every sub-term.

Plated.transform over this optic — bottom-up rewrite of every sub-term.

Attributes

Source
Plated.scala
def universeOf(s: S): List[S]

Plated.universe over this optic — every sub-term, pre-order, s first.

Plated.universe over this optic — every sub-term, pre-order, s first.

Attributes

Source
Plated.scala