liveBook · Manning

Continuation

As explained in Functional Design and Architecture: Examples in Haskell

A continuation is a function representing the remainder of a computation and receiving the result of an intermediate operation.

A continuation is a function that receives an operation’s result and describes what happens next. In an embedded language, it turns separate instructions into one directed computation: an action produces a value, then passes that value to the next script. This makes dependencies explicit. For example, setup can produce a Controller value that registration must consume, so a registration cannot be fully declared without prior setup. section 5.2.2

This structure improves on a flat list of commands that names controllers with bare strings. A list can place registration before setup, omit setup entirely, or name the wrong controller. Storing a continuation such as Controller -> Hdl in SetupController replaces a guessed identifier with the actual result of setup. The script becomes tree-like: later branches are nested beneath the actions whose results they need. section 5.2.2

Passing a result forward

A sensor operation can carry a continuation of type Either String Measurement -> Hdl. After interpretation obtains either an error or a measurement, it invokes that function to construct the remaining script—for example, a Report action containing the displayed result. Naming the function separately can make the script clearer than an inline lambda. section 5.2.2

Free monads retain the same idea while hiding much of the nested-lambda syntax. Each algebra operation stores a function from its result to next; bind composes these continuations into a sequential script. Smart constructors initially use Pure as the continuation placeholder. Binding replaces that placeholder with the next computation, leaving one final Pure value that returns the completed result. section 6.3.1 section 6.3.2

The required Functor instance preserves an operation’s domain data while composing a new function with its existing continuation. This is how the free-monad machinery nests one script inside another. During interpretation, execution repeatedly unrolls a Free layer and a domain-action layer; each interpreted action applies its continuation to obtain the next script, until Pure ends the chain. section 6.3.3 section 6.3.5

Listing 5.4 A tree-like script
script :: Hdl
script =
 [ SetupController "left booster" "left b ctrl" aaaController86Passport
 
   ( \lCtrl ->
     [ RegisterComponent lCtrl "nozzle1-t" aaaTemperature25Passport
     , RegisterComponent lCtrl "nozzle1-p" aaaPressure02Passport
     , SetupController "right booster" "right b ctrl" aaaController86Passport
 
       ( \rCtrl ->
         [ RegisterComponent rCtrl "nozzle2-t" aaaTemperature25Passport
         , RegisterComponent rCtrl "nozzle2-p" aaaPressure02Passport
         , ReadSensor lCtrl "nozzle1-t"
 
           ( \eMeasurement -> [ Report (show eMeasurement) ] )
         ]
       )
     ]
   )
 ]

This controller-and-sensor script makes the dependency tree visible: setup yields controller values, and later registrations and reads occur inside continuations that receive them. section 5.2.2

Continuations are also useful when composing hierarchical languages. An enclosing operation can hold a script that returns some result together with a continuation that accepts exactly that result. Generalized algebraic data types express this local type relationship, allowing a logic script to evaluate hardware or device-control actions and continue with their typed outcomes. section 6.4.2

How Functional Design and Architecture: Examples in Haskell covers it

How deep it goes
Explains continuation fields, bind-based nesting, Functor composition, and interpreter unrolling through typed eDSL implementations.
Examples
Uses controller setup and sensor reporting, sandwich construction, and terminal read-and-print scenarios.
What it assumes
Introduces Functor mapping but expects some familiarity with functional idioms when implementing free-monad machinery.
What you can do after
Build it from scratch by adding typed continuation fields and interpreting each produced next script until termination.
How it connects
Connects continuations with embedded domain-specific languages, free monads, bind, Functor, interpreters, and generalized algebraic data types.

Also explained in

Compare how 3 books explain continuation →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Functional Design and Architecture: Examples in Haskell. The section links point to the parts of the book it draws on.