Schemes
Typed recursion schemes as composable optics, over a user-supplied pattern functor F[_] (+ Traverse[F]) and the Basis (Project/Embed) correspondence to the recursive type S.
==The thesis==
A recursion scheme is an dev.constructive.eo.optics.Optic over the dev.constructive.eo.data.Direct carrier whose existential X is the index of the recursion — what the scheme retains — and the (co)free (co)monads are the universal indices:
| scheme | X |
index |
|---|---|---|
| cata | Nothing |
the forgetful (trivial) fold |
| zygo | F[(B, A)] |
store comonad over an auxiliary carrier B |
| para | F[(S, A)] |
the store-comonad complement (subterms) |
| histo | zoo.Attr = νX. A × F[X] |
the cofree comonad (course-of-value fold) |
| ana | S |
the materialising unfold |
| cozygo | Either[B, A] |
g-apo residual over an auxiliary coalgebra |
| apo | Either[S, A] |
the Prism residual (graft, build-side) |
| futu | zoo.Coattr = μX. A + F[X] |
the free monad (multi-layer unfold) |
para/histo refine cata's index up the comonad tower; apo/futu refine ana's up the monad tower. (para's existential is the writable-Lens complement — get-put holds definitionally, put-get only under algebra-coherence, so the lawful writable put is a scoped follow-up.)
The towers also have an auxiliary rung between the trivial and store/prism indices: zygo (X = F[(B, A)], the store comonad over an arbitrary carrier B — para is zygo at B = S) and its mutual-recursion generalisation mutu (X = F[(A, B)]), with build-side duals cozygo (X = Either[B, A], g-apo) and comutu (X = Either[A, B]).
Orthogonal to both towers is the natural-transformation axis — prepro / postpro keep the trivial index (cata/ana-shaped) and instead pre/post-compose the layer optic (fLayer) with an accumulating η : F ~> F, so a node at depth k is transformed k times (O(n · depth); η = id recovers cata/ana).
==hylo is the fusion, not a primitive — and meta is the honest non-fusion==
ana is a build (Review-shaped) and cata a node-blind fold (Getter-shaped); the build⇄read seam ana.cross(cata) (definitionally ana.reverse.andThen(cata)) fuses — the citizens keep their coalg/alg alive — into zoo.Hylo, building no intermediate S. The FusionSpec pins the hylo law and witnesses the deforestation (the fused refold never calls project/embed).
The fold→unfold seam cata.meta(ana) is the direction-dual (meta, the metamorphism), and it cannot fuse: fold and unfold range over different functors, so the neck value is materialised (the zoo.Meta existential is X = A, not Nothing). The 2×2 the two seams complete — refold vs metamorphism × trivial vs universal index — is zoo.Hylo / zoo.Meta / zoo.Chrono / zoo.MetaChrono; the quadrant's diagonals are zoo.Dyna (ana.cross(histo)) and zoo.Codyna (futu.cross(cata)). zoo.Elgot / zoo.Coelgot are the short-circuit / seed-reading refold variants.
==Shape==
Every scheme is a final class in zoo carrying its run/build function (the construction and machine-wiring live in each class's companion); this object is the user-facing factory listing — one-line delegations — plus fLayer. All schemes run on one stack-safe engine (Machines.foldLayered): a < 512-deep on-stack fast path falling back per deep subtree to a heap ArrayDeque machine — stack-safe to 10⁶, tested.
Attributes
- Source
- Schemes.scala
- Graph
-
- Supertypes
-
class Objecttrait Matchableclass Any
- Self type
-
Schemes.type
Members list
Value members
Concrete methods
Anamorphism — an unfold coalg: Seed => F[Seed] (zoo.Ana, X = S). .reverseGet.
Anamorphism — an unfold coalg: Seed => F[Seed] (zoo.Ana, X = S). .reverseGet.
Attributes
- Source
- Schemes.scala
Monadic anamorphism — an effectful unfold coalg: Seed => M[F[Seed]] (zoo.BuildM, X = S). .reverseGet yields M[S]. At M = Id it is exactly ana.
Monadic anamorphism — an effectful unfold coalg: Seed => M[F[Seed]] (zoo.BuildM, X = S). .reverseGet yields M[S]. At M = Id it is exactly ana.
Attributes
- Source
- Schemes.scala
Apomorphism — an unfold that grafts finished subtrees, coalg: A => F[Either[S, A]] (zoo.Apo, X = Either[S, A]). Left grafts by reference (O(1)). .reverseGet. All-Right degenerates to ana.
Apomorphism — an unfold that grafts finished subtrees, coalg: A => F[Either[S, A]] (zoo.Apo, X = Either[S, A]). Left grafts by reference (O(1)). .reverseGet. All-Right degenerates to ana.
Attributes
- Source
- Schemes.scala
Monadic apomorphism — an effectful grafting unfold coalg: A => M[F[Either[S, A]]] (zoo.BuildM, X = Either[S, A]). Left(s) grafts a finished subtree by reference (O(1), no effect). .reverseGet yields M[S].
Monadic apomorphism — an effectful grafting unfold coalg: A => M[F[Either[S, A]]] (zoo.BuildM, X = Either[S, A]). Left(s) grafts a finished subtree by reference (O(1), no effect). .reverseGet yields M[S].
Attributes
- Source
- Schemes.scala
apo's per-slot residual worn on the data.Affine build seam — a composable scatter optic (Left(s) → Done(s) the O(1) graft, Right(a) → Step((), a) keep unfolding). X = (S, Unit). Composes via data.Affine.assoc and the data.Affine.either2affine bridge; it is the carried decoration apo's engine itself drives (see zoo.Apo).
apo's per-slot residual worn on the data.Affine build seam — a composable scatter optic (Left(s) → Done(s) the O(1) graft, Right(a) → Step((), a) keep unfolding). X = (S, Unit). Composes via data.Affine.assoc and the data.Affine.either2affine bridge; it is the carried decoration apo's engine itself drives (see zoo.Apo).
Attributes
- Source
- Schemes.scala
Catamorphism — a node-blind fold alg: F[A] => A (zoo.Cata, X = Nothing). .get.
Catamorphism — a node-blind fold alg: F[A] => A (zoo.Cata, X = Nothing). .get.
Attributes
- Source
- Schemes.scala
Monadic catamorphism — a node-blind fold alg: F[A] => M[A] (zoo.FoldM, X = Nothing). .get yields M[A]. At M = Id it is exactly cata.
Monadic catamorphism — a node-blind fold alg: F[A] => M[A] (zoo.FoldM, X = Nothing). .get yields M[A]. At M = Id it is exactly cata.
Attributes
- Source
- Schemes.scala
Chronomorphism — the fused free-unfold → cofree-fold A => B (zoo.Chrono), hylo at the universal indices. Definitionally futu(coalg).cross(histo(algebra)).
Chronomorphism — the fused free-unfold → cofree-fold A => B (zoo.Chrono), hylo at the universal indices. Definitionally futu(coalg).cross(histo(algebra)).
Attributes
- Source
- Schemes.scala
Monadic chronomorphism — the fused effectful free-unfold → cofree-fold A => M[B] (zoo.FoldM, X = Nothing), hyloM at the universal indices. Traverse[F] only.
Monadic chronomorphism — the fused effectful free-unfold → cofree-fold A => M[B] (zoo.FoldM, X = Nothing), hyloM at the universal indices. Traverse[F] only.
Attributes
- Source
- Schemes.scala
Codynamorphism — the fused free-unfold → node-blind-fold A => B (zoo.Codyna, the mirror of dyna). Definitionally futu(coalg).cross(cata(alg)).
Codynamorphism — the fused free-unfold → node-blind-fold A => B (zoo.Codyna, the mirror of dyna). Definitionally futu(coalg).cross(cata(alg)).
Attributes
- Source
- Schemes.scala
Co-Elgot — a hylo whose fold reads the seed, alg: (A, F[B]) => B (zoo.Coelgot). Ignoring the seed degenerates to hylo.
Co-Elgot — a hylo whose fold reads the seed, alg: (A, F[B]) => B (zoo.Coelgot). Ignoring the seed degenerates to hylo.
Attributes
- Source
- Schemes.scala
Comutumorphism — the build-side dual of mutu: two mutually co-recursive coalgebras A => F[Either[A, B]] / B => F[Either[A, B]], entered at an A (zoo.Comutu, X = Either[A, B]). Generalises cozygo; degenerates to ana when one coalgebra suffices. .reverseGet.
Comutumorphism — the build-side dual of mutu: two mutually co-recursive coalgebras A => F[Either[A, B]] / B => F[Either[A, B]], entered at an A (zoo.Comutu, X = Either[A, B]). Generalises cozygo; degenerates to ana when one coalgebra suffices. .reverseGet.
Attributes
- Source
- Schemes.scala
Cozygomorphism (g-apomorphism) — the build-side dual of zygo: an auxiliary coalgebra aux: B => F[B] alongside the main coalg: A => F[Either[B, A]] (zoo.Cozygo, X = Either[B, A]). Left(b) keeps unfolding through aux; all-Right degenerates to ana. .reverseGet.
Cozygomorphism (g-apomorphism) — the build-side dual of zygo: an auxiliary coalgebra aux: B => F[B] alongside the main coalg: A => F[Either[B, A]] (zoo.Cozygo, X = Either[B, A]). Left(b) keeps unfolding through aux; all-Right degenerates to ana. .reverseGet.
Attributes
- Source
- Schemes.scala
Dynamorphism — the fused plain-unfold → cofree-fold A => B (zoo.Dyna). Definitionally ana(coalg).cross(histo(alg)).
Dynamorphism — the fused plain-unfold → cofree-fold A => B (zoo.Dyna). Definitionally ana(coalg).cross(histo(alg)).
Attributes
- Source
- Schemes.scala
The single layer optic for a pattern functor F: project/embed worn as core's dev.constructive.eo.data.MultiFocus carrier — MultiFocus[F][X, A] = (X, F[A]), the Traversal/AlgLens/Grate carrier. to(s) = ((), project(s)) and from((_, fs)) = embed(fs), so it is a genuine Optic[S, S, S, S, MultiFocus[F]]: a typed single-layer self-traversal whose foci are the node's immediate children F[S].
The single layer optic for a pattern functor F: project/embed worn as core's dev.constructive.eo.data.MultiFocus carrier — MultiFocus[F][X, A] = (X, F[A]), the Traversal/AlgLens/Grate carrier. to(s) = ((), project(s)) and from((_, fs)) = embed(fs), so it is a genuine Optic[S, S, S, S, MultiFocus[F]]: a typed single-layer self-traversal whose foci are the node's immediate children F[S].
Because it now rides the same carrier as dev.constructive.eo.optics.Plated.plate and dev.constructive.eo.optics.Traversal.each, it composes with the rest of core: read the immediate foci via .foldMap (Foldable[F]), rewrite them via .modify / .replace (Functor[F]), or effect over them via .modifyA / .all (Traverse[F]) — the read+write upgrade over the former read-only Forget[F] spelling. It is one layer, not the recursion; the Plated.fromBasis derivation is its recursive face, and the schemes drive to/from themselves. X = Unit: the F-shape (constructor + arity) rides inside the foci F[S], so embed needs no extra leftover.
Attributes
- Source
- Schemes.scala
Futumorphism — a multi-layer unfold coalg: A => F[Coattr[F, A]] (zoo.Futu, X = Coattr, the free monad). .reverseGet. All-Pure degenerates to ana.
Futumorphism — a multi-layer unfold coalg: A => F[Coattr[F, A]] (zoo.Futu, X = Coattr, the free monad). .reverseGet. All-Pure degenerates to ana.
Attributes
- Source
- Schemes.scala
Monadic futumorphism — an effectful multi-layer unfold coalg: A => M[F[Coattr[F, A]]] (zoo.BuildM, X = Coattr[F, A], the free monad). Roll unrolls a prebuilt layer with no effect. .reverseGet yields M[S].
Monadic futumorphism — an effectful multi-layer unfold coalg: A => M[F[Coattr[F, A]]] (zoo.BuildM, X = Coattr[F, A], the free monad). Roll unrolls a prebuilt layer with no effect. .reverseGet yields M[S].
Attributes
- Source
- Schemes.scala
Histomorphism — a course-of-value fold alg: F[Attr[F, A]] => A (zoo.Histo, X = Attr, the cofree comonad). .get. Heads-only degenerates to cata.
Histomorphism — a course-of-value fold alg: F[Attr[F, A]] => A (zoo.Histo, X = Attr, the cofree comonad). .get. Heads-only degenerates to cata.
Attributes
- Source
- Schemes.scala
Monadic histomorphism — a course-of-value effectful fold alg: F[Attr[F, A]] => M[A] (zoo.FoldM, X = Attr[F, A], the cofree comonad). .get yields M[A].
Monadic histomorphism — a course-of-value effectful fold alg: F[Attr[F, A]] => M[A] (zoo.FoldM, X = Attr[F, A], the cofree comonad). .get yields M[A].
Attributes
- Source
- Schemes.scala
Hylomorphism — the fused unfold→fold Seed => A (zoo.Hylo). Definitionally ana(coalg).cross(cata(alg)).
Hylomorphism — the fused unfold→fold Seed => A (zoo.Hylo). Definitionally ana(coalg).cross(cata(alg)).
Attributes
- Source
- Schemes.scala
Monadic hylomorphism — the fused effectful refold Seed => M[A] (zoo.FoldM, X = Nothing), building no intermediate S. Traverse[F] only. At M = Id it is hylo.
Monadic hylomorphism — the fused effectful refold Seed => M[A] (zoo.FoldM, X = Nothing), building no intermediate S. Traverse[F] only. At M = Id it is hylo.
Attributes
- Source
- Schemes.scala
Metamorphism — the fold-then-unfold S => T (zoo.Meta, X = A, the neck). Fold the F-recursive S to A, then unfold a G-recursive T. Definitionally cata(alg).meta( ana(coalg)).
Metamorphism — the fold-then-unfold S => T (zoo.Meta, X = A, the neck). Fold the F-recursive S to A, then unfold a G-recursive T. Definitionally cata(alg).meta( ana(coalg)).
Attributes
- Source
- Schemes.scala
Metamorphism at the universal indices — the fold→unfold dual of chrono (zoo.MetaChrono): course-of-value fold then multi-layer unfold. Definitionally histo(algebra).meta(futu(coalg)).
Metamorphism at the universal indices — the fold→unfold dual of chrono (zoo.MetaChrono): course-of-value fold then multi-layer unfold. Definitionally histo(algebra).meta(futu(coalg)).
Attributes
- Source
- Schemes.scala
Mutumorphism — a fold by mutual recursion: two algebras F[(A, B)] => A / F[(A, B)] => B compute a pair per node, returning the A half (zoo.Mutu, X = F[(A, B)]). Generalises zygo (whose aux is an algB blind to the A half). .get.
Mutumorphism — a fold by mutual recursion: two algebras F[(A, B)] => A / F[(A, B)] => B compute a pair per node, returning the A half (zoo.Mutu, X = F[(A, B)]). Generalises zygo (whose aux is an algB blind to the A half). .get.
Attributes
- Source
- Schemes.scala
Paramorphism — a subterm-retaining fold alg: F[(S, A)] => A (zoo.Para, X = F[(S, A)]). .get. Ignoring the S half degenerates to cata.
Paramorphism — a subterm-retaining fold alg: F[(S, A)] => A (zoo.Para, X = F[(S, A)]). .get. Ignoring the S half degenerates to cata.
Attributes
- Source
- Schemes.scala
The paramorphism promoted from a Getter to a Lens — para is the read (get), this adds the write (enplace), yielding a core dev.constructive.eo.optics.GetReplaceLens that composes with hand-written / derived Lenses on the fused Tuple2 path.
The paramorphism promoted from a Getter to a Lens — para is the read (get), this adds the write (enplace), yielding a core dev.constructive.eo.optics.GetReplaceLens that composes with hand-written / derived Lenses on the fused Tuple2 path.
'''Why enplace is a parameter, not derived.''' para is unconditionally a Getter, but a fold result is not in general a recoverable component of S. The automatic put the store-comonad story suggests — re-embed the retained subterms (X = F[(S, A)]) — makes get-put hold definitionally yet leaves put-get conditional on the algebra having a coherent inverse. Rather than ship a Lens that is only conditionally lawful, the coherent put-direction is supplied by the caller; get / enplace then obey the ordinary Lens laws. (The fully-automatic, read-only decorated optic — each child paired with its fold result, X = F[(S, A)], the store comonad over subterms — is the natural enrichment of fLayer and a follow-up; it stays read-only because the decoration cannot be lawfully written.)
Value parameters
- alg
-
the subterm-retaining fold
F[(S, A)] => A— theget, a genuine paramorphism. - enplace
-
the coherent put: rebuild an
Swhosegetis the new focus.
Attributes
- Source
- Schemes.scala
Monadic paramorphism — a subterm-retaining effectful fold alg: F[(S, A)] => M[A] (zoo.FoldM, X = F[(S, A)]). .get yields M[A].
Monadic paramorphism — a subterm-retaining effectful fold alg: F[(S, A)] => M[A] (zoo.FoldM, X = F[(S, A)]). .get yields M[A].
Attributes
- Source
- Schemes.scala
Postpromorphism — the build-side mirror of prepro: an ana-shaped unfold (coalg: A => F[A], X = S) that applies η : F ~> F after each step (zoo.Postpro). η = id degenerates to ana. .reverseGet. O(n · depth).
Postpromorphism — the build-side mirror of prepro: an ana-shaped unfold (coalg: A => F[A], X = S) that applies η : F ~> F after each step (zoo.Postpro). η = id degenerates to ana. .reverseGet. O(n · depth).
Attributes
- Source
- Schemes.scala
Prepromorphism — a cata-shaped fold (alg: F[A] => A, X = Nothing) that applies a natural transformation η : F ~> F before recursing, so a node at depth k sees η applied k times (zoo.Prepro). η = id degenerates to cata. .get. O(n · depth).
Prepromorphism — a cata-shaped fold (alg: F[A] => A, X = Nothing) that applies a natural transformation η : F ~> F before recursing, so a node at depth k sees η applied k times (zoo.Prepro). η = id degenerates to cata. .get. O(n · depth).
Attributes
- Source
- Schemes.scala
Zygomorphism — a fold with an auxiliary algebra aux: F[B] => B feeding the main alg: F[(B, A)] => A (zoo.Zygo, X = F[(B, A)]). The comonad-tower rung between cata and para: para is zygo at B = S, aux = embed; ignoring the B half degenerates to cata. .get.
Zygomorphism — a fold with an auxiliary algebra aux: F[B] => B feeding the main alg: F[(B, A)] => A (zoo.Zygo, X = F[(B, A)]). The comonad-tower rung between cata and para: para is zygo at B = S, aux = embed; ignoring the B half degenerates to cata. .get.
Attributes
- Source
- Schemes.scala