liveBook · Manning

runFree

As explained in Functional Programming in Scala, Second Edition

runFree is a book-defined operation that interprets a Free program by translating its instructions into a target monad.

runFree interprets a Free[F, A] program in a target monad G by translating every instruction F[x] into G[x]. It separates a program’s description from the interpreter’s effects: the same console program can run through real I/O, a reader, state, or a test interpreter. section 13.4.2 section 13.4.3

Interpretation proceeds through three cases after step normalizes the Free program:

  • Return(a) becomes G.unit(a). section 13.4.2
  • Suspend(r) becomes t(r), where t is polymorphic and converts F[x] to G[x] for every encountered x. section 13.4.2
  • FlatMap(Suspend(r), f) translates r, then continues with f through the target monad’s flatMap. section 13.4.2
  • step reassociates nested FlatMaps and reduces FlatMap(Return(x), f), leaving only shapes that runFree can handle. section 13.10

Interpreting console programs

A Free[Console, A] program can be interpreted with c.toThunk to produce Function0[A], with c.toPar to produce Par[A], or with c.toState to produce a stateful test interpreter. unsafeRunConsole selects the thunk interpreter and then runs it with runTrampoline. section 13.4.2 section 13.4.3

enum Free[F[_], A]:
  ...
  def runFree[G[_]](t: [x] => F[x] => G[x])(using G: Monad[G]): G[A] =    #1
    step match
      case Return(a) => G.unit(a)
      case Suspend(r) => t(r)
      case FlatMap(Suspend(r), f) => t(r).flatMap(a => f(a).runFree(t))
      case FlatMap(_, _) =>
        sys.error("Impossible, `step` eliminates these cases")

Inspect the compact runFree definition, including its polymorphic translation function and three interpretation cases. section 13.4.2

How Functional Programming in Scala, Second Edition covers it

How deep it goes
Explains polymorphic instruction translation, normalization with step, and recursive monadic interpretation, without detailing each target monad’s internals.
Examples
Uses Console programs interpreted as thunks, Par values, Reader values, or stateful input-output buffers.
What it assumes
Assumes Free constructors, flatMap, Monad, and higher-kinded types while motivating polymorphic functions from console interpretation.
What you can do after
Apply via a polymorphic interpreter to execute Free programs or redirect them toward testing and pure simulation.
How it connects
Connects Free, monads, natural transformations, interpreters, State, Reader, Par, Function0, and trampoline evaluation.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Functional Programming in Scala, Second Edition. The section links point to the parts of the book it draws on.