`step` is an interpreter helper for `Free[F, A]` that exposes a small set of executable shapes before `run` continues. It rewrites a computation until it is a `Return`, a `Suspend`, or a right-associated `FlatMap(Suspend(fx), f)`. This normalization keeps the runner focused on immediate work rather than every possible nesting of `flatMap`. section 13.10
The difficult case is a left-nested bind. A value shaped like `FlatMap(FlatMap(fx, f), g)` is reassociated as `fx.flatMap(x => f(x).flatMap(g))`, then stepped again. A bind whose source is already `Return(x)` is simplified by applying its continuation, `f(x)`, and stepping that result. All remaining shapes are already normalized. section 13.10
@annotation.tailrec final def step: Free[F, A] = this match case FlatMap(FlatMap(fx, f), g) => fx.flatMap(x => f(x).flatMap(g)).step case FlatMap(Return(x), f) => f(x).step case _ => this
The implementation makes the two rewrites explicit: reassociate nested `FlatMap` values, eliminate `FlatMap(Return(x), f)`, and leave normalized cases unchanged. section 13.10
Running a normalized Free program
After calling `step`, `run` has three productive cases: lift a returned value with `unit`, return a suspended effect directly, or sequence one suspended effect with the remaining continuation. The final wildcard is marked impossible because `step` has removed left-nested binds and binds over `Return`. section 13.10
The same operational idea appears in `Pull`: stepping incrementally either reports final result `R` or emits one output `O` with a remainder pull. Its `FlatMap` case reassociates nested binds and propagates the continuation onto the tail, allowing `fold` to repeatedly consume one step at a time. section 15.2
When pulls gain error handling, stepping also interprets nested error handlers. It right-associates nested handlers, delegates failures to `handleErrorWith`, and carries an unchanged handler forward with the remainder. With resource scopes, a step additionally reports the active scope so evaluation can open, restore, and close scopes correctly. section 15.3.2 section 15.3.3
