liveBook · Manning

LogicControl

As explained in Functional Design and Architecture: Examples in Haskell

LogicControl is the book's embedded domain-specific language for expressing spaceship control logic and higher-level domain operations.

LogicControl is an embedded language for orchestrating spaceship control work at the business-logic level. It can define and prepare hardware through Hdl, invoke device operations through DeviceControl, report messages, and keep key–value state. Its central design problem is coordinating those capabilities without making every lower-level language depend on every other one. section 5.2.3 section 8.2.2

A naïve list-based design lets Hdl and DeviceControl continuations return to LogicControl, while LogicControl evaluates their scripts. That enables a flow such as creating a controller, registering a component, reading a sensor, and reporting the result—but creates cyclic language and module dependencies, deeply nested scripts, and poor cohesion. section 5.2.3 section 6.4.2

Listing 5.6 Highly entangled languages
type Hdl = [HdlMethod]                            #1
  
data HdlMethod
  = SetupController
      DeviceName
      ControllerName
      ComponentPassport
      (Controller -> LogicControl)                #2
  | RegisterComponent
      Controller
      ComponentIndex
      ComponentPassport
  
type DeviceControl = [DeviceControlMethod]        #3
  
data DeviceControlMethod
  = GetStatus
      Controller
      (Either String Status -> LogicControl)      #4
  | ReadSensor
      Controller
      ComponentIndex
      (Either String Measurement -> LogicControl) #5
  
type LogicControl = [LogicControlMethod]          #6
  
data LogicControlMethod
  = EvalHdl Hdl                                   #7
  | EvalDeviceControl DeviceControl
  | Report Message

Inspect the entangled version to see why embedding Hdl and DeviceControl in both directions makes LogicControl scripts and dependencies hard to manage. section 5.2.3

A first improvement makes subordinate languages parameterized by their continuation type. LogicControl remains the top-level language and chooses Hdl LogicControl or DeviceControl LogicControl when nesting them; the subordinate languages no longer name LogicControl themselves. This preserves the scripting experience while separating their modules and responsibilities. section 5.2.4

The fuller design uses free monads. LogicControl becomes Free LogicControlMethod, with smart constructors for operations such as report and store. GADT-based constructors can evaluate Hdl and DeviceControl operations while preserving each operation’s result type, so a script can bind created controllers, read typed sensor results, and turn hardware failures into logic-level failures. section 6.4.2

LogicControl operations establish a hierarchy of responsibilities:

  • EvalHdl runs hardware-definition work, such as setting up controllers or registering components. section 5.2.4 section 6.4.2
  • EvalDeviceControlMethod brings device commands such as status checks and sensor reads into control logic. section 6.4.2
  • Report communicates a message, although its intended reporting mechanism should be made explicit in the interface. section 8.2.2
  • Store and Load model mutable key–value state; a simulation may interpret that state with concurrently mutable in-memory structures. section 8.2.2

Booster status and temperature workflows

A control script can create two boosters through Hdl, obtain each controller’s status through DeviceControl, and combine hardware failures into a LogicFailure. Another workflow creates boosters, reads a nozzle temperature, reports an error on failure, or reports the measurements and a confirmation message on success. These scripts keep orchestration in LogicControl while leaving hardware definition and device primitives below it. section 6.4.2 section 8.2.2

How Functional Design and Architecture: Examples in Haskell covers it

How deep it goes
Develops list-based nesting into free-monad and GADT-based typed composition, deferring the wider calculations and automation domain.
Examples
Uses controller setup, thermometer registration, sensor reads, booster-status aggregation, temperature reporting, and key–value reupload workflows.
What it assumes
Assumes familiarity with Haskell ADTs and eDSLs while introducing parameterization, free-monad structure, and typed operation results progressively.
What you can do after
Build it from scratch as a hierarchical, typed free eDSL that composes hardware and device operations.
How it connects
Connects embedded domain-specific languages with algebraic data types, parameterized ADTs, free monads, GADTs, continuations, and concurrency.

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.