liveBook · Manning

LangL

As explained in Functional Design and Architecture: Examples in Haskell

LangL is a book-specific language for application-level computations that can perform input-output effects such as logging.

LangL is a free-monadic language for application business logic. Instead of running raw IO directly, a LangL script describes operations such as delays, random-number generation, and mutable-state access; interpreters supply their runtime behavior. This keeps domain logic separate from application setup and process management. section 9.1.3 section 9.2.3

The separation is architectural. AppL prepares the application environment, configuration, processes, and their relationships, while LangL describes the logic that runs within that environment. Once work is evaluated in additional processes, that work is restricted to LangL scripts, making unconstrained nested thread creation unrepresentable through the business-logic interface. section 9.1.3

Listing 9.1 Two languages for the business logic layer
data LangF next where                                              #1
  Delay        :: Int -> (() -> next)          -> LangF next
  GetRandomInt :: (Int, Int) -> (Int -> next)  -> LangF next
  NewVar       :: a -> (IORef a -> next)       -> LangF next
  ReadVar      :: IORef a -> (a -> next)       -> LangF next
  WriteVar     :: IORef a -> a -> (() -> next) -> LangF next
  
type LangL = Free LangF                                            #2
  
delay        :: Int          -> LangL ()                           #3
getRandomInt :: (Int, Int)   -> LangL Int
newVar       :: a            -> LangL (IORef a)
readVar      :: IORef a      -> LangL a
writeVar     :: IORef a -> a -> LangL ()
  
data AppF next where                                               #4
  EvalLang    :: LangL a  -> (a -> next)  -> AppF next
  ForkProcess :: LangL () -> (() -> next) -> AppF next
  
type AppL = Free AppF
  
forkProcess :: LangL () -> AppL ()                                 #5
evalLang    :: LangL a  -> AppL a

LangL is defined as Free LangF. Its smart constructors expose delay, random values, and IORef operations, while AppL can evaluate a LangL script or fork one as a process. section 9.1.3

Use the interface to make allowed business operations explicit:

  • Describe pauses and random values with LangL operations rather than performing them directly. section 9.1.3
  • Create, read, and write state only through LangL wrappers, not through arbitrary IO actions. section 9.2.3
  • Move unsafe shared-state updates into STM transactions when concurrent business logic needs them. section 9.2.3
  • Adapt focused subsystems, such as logging, into LangL rather than giving business code a broad undifferentiated interface. section 10.1.1

Wrapping IORef operations does not make their runtime effects disappear; it prevents client scripts from directly invoking IO. Allowing a general evalIO operation would let any LangL function introduce arbitrary effects, obscuring variable creation, ownership, and cross-thread access. For shared reporting state, STM provides a safer abstraction: the business operation is expressed as STM and executed atomically by the interpreter. section 9.2.3 section 9.2.3

Meteor reporting and logging

A meteor observer can generate a random meteor, add it to a reporting channel, and delay before the next observation, all as LangL actions. The application evaluates setup logic and forks the repeated observer as a process. Logging is added by adapting a LoggerL debug message into LangL, leaving formatting and console output to the logger interpreter. section 9.1.3 section 10.1.1

LangL is one layer in a hierarchy, not a claim that every concern belongs in one effect list. Its interface should stay focused on a coherent subsystem level. Additional languages can be nested where needed, but several free-monadic layers are not automatically appropriate for every application. section 9.1.3 section 10.1.1

How Functional Design and Architecture: Examples in Haskell covers it

How deep it goes
Defines operations and interpreters for state and STM, while deferring concrete effect execution to implementation layers.
Examples
Uses meteor generation, reporting channels, repeated observer processes, and debug logging to demonstrate LangL scripts.
What it assumes
Assumes familiarity with free monads, IO, IORef, STM, and concurrent processes rather than teaching them from zero.
What you can do after
Build it from scratch as a focused free-monadic business-logic interface with interpreter-defined effects.
How it connects
Connects free monads with AppL, IORef, STM, LoggerL, interpreters, and process 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.