Alterator

Alterator is the base trait for stages that wrap a single inner stage — the alterand. It declares the abstract alterand member and seals dispose to forward to alterand.dispose(), so concrete subclasses never need to handle disposal themselves.

The type parameter S is covariant and bounded to Stage.Any, preserving the concrete type of the alterand in the wrapper's static type without information loss.

Do not mix Alterator with traits that introduce independent state or their own evolution logic — for example, SAMStage or Stagnation. Alterator assumes that alterand owns all resources and controls all evolution. A co-mixed trait that adds its own resources or overrides evolution without coordinating with the alterand breaks that contract silently: its resources will not be released and its transitions will be ignored.

The base package provides four type aliases built on Alterator:

Alias Meaning
UnaryOperator[+S, -I, +O, +E] Wraps any Stage[I, ?, ?]; may change all three type parameters
Decorator[-I, +O, +E] Wraps a Stage[I, O, E] and preserves its full type
Alteration[-IS, +OS] A function IS => OS that transforms one stage type into another
Decoration[I, O, E] An Alteration[Stage[I, O, E], Stage[I, O, E]] — the shape passed to Evolution.map

Decorator is the alias to reach for when building middleware that wraps a stage without changing its interface:

import h8io.stages.*
import h8io.stages.base.*
class Logged[I, O, E](val alterand: Stage[I, O, E]) extends Decorator[I, O, E] {
  override def apply(in: I): Yield[I, O, E] = {
    println(s"apply($in)")
    alterand(in)
  }

  override def skip(): Evolution[I, O, E] = alterand.skip()
}

val logged = new Logged(DoubleInt)
// logged: Logged[Int, Int, Nothing] = <function1>
logged(10)
// apply(10)
// res0: Yield[Int, Int, Nothing] = Some(
//   out = 20,
//   status = Success,
//   evolution = <function1>
// )
logged.skip()
// res1: Evolution[Int, Int, Nothing] = <function1>

Alteration and Decoration are the shapes used when passing stage transformations as values — for example, to Evolution.map.