Swap

Swap is a polymorphic singleton: a single Fn[(Any, Any), (Any, Any)] instance that swaps the two elements of a pair, always yielding Status.Success. Use Swap[L, R] to obtain a typed Fn[(L, R), (R, L)].

import h8io.stages.*
import h8io.stages.std.*
val stage = Swap[String, Int]
// stage: base.Fn[(String, Int), (Int, String)] = <function1>
stage(("a", 1))
// res0: Yield.Some[(String, Int), (Int, String), Nothing] = Some(
//   out = (1, "a"),
//   status = Success,
//   evolution = <function1>
// )

Reduce and Fold both call their op in the "left" convention, op((accumulator, output)). Composing Swap[R, O] ~> op in front of an op written the other way around — (output, accumulator) — adapts it without needing a separate ReduceRight/FoldRight operator. For a non-commutative op this changes the result:

import h8io.stages.base.*
import h8io.stages.cycles.*

object Once extends SAMStage[Unit, Int, Nothing] {
  override def apply(in: Unit): Yield[Unit, Int, Nothing] = Yield.Some(3, Status.complete, this)
}

object Sub extends Fn[(Int, Int), Int] {
  override protected def f(in: (Int, Int)): Int = in._1 - in._2
}

Fold(Once, Sub)((10, ()))                   // "left": accumulator - output
// res1: Yield.Some[(Int, Unit), Int, Nothing] = Some(
//   out = 7,
//   status = Success,
//   evolution = ConstEvolution(
//     stage = Fold(alterand = <function1>, op = <function1>),
//     _dispose = h8io.stages.cycles.Fold$$$Lambda$19863/0x00007f58029a16a0@1aa8cc99
//   )
// )
Fold(Once, Swap[Int, Int] ~> Sub)((10, ())) // "right": output - accumulator, via Swap
// res2: Yield.Some[(Int, Unit), Int, Nothing] = Some(
//   out = -7,
//   status = Success,
//   evolution = ConstEvolution(
//     stage = Fold(
//       alterand = <function1>,
//       op = AndThen(upstream = <function1>, downstream = <function1>)
//     ),
//     _dispose = h8io.stages.cycles.Fold$$$Lambda$19863/0x00007f58029a16a0@250acb5
//   )
// )