ExamplesBy LevelBy TopicLearning Paths
250 Expert

Grand Synthesis

Functional Programming

Tutorial Video

Text description (accessibility)

This video demonstrates the "Grand Synthesis" functional Rust example. Difficulty level: Expert. Key concepts covered: Functional Programming. This capstone example weaves together every major concept from this series: recursion schemes, optics, free monads, comonads, type-level programming, parser combinators, and categorical abstractions. Key difference from OCaml: | Aspect | Rust | OCaml |

Tutorial

The Problem

This capstone example weaves together every major concept from this series: recursion schemes, optics, free monads, comonads, type-level programming, parser combinators, and categorical abstractions. The goal is to build a small but complete functional language interpreter that demonstrates how these patterns compose: the AST is defined as a fixed-point type, evaluation uses a catamorphism, variable scoping uses the Reader monad, a free monad models effectful operations, lenses navigate nested state, and Cofree annotates the AST with type information.

🎯 Learning Outcomes

  • • Compose recursion schemes, optics, monads, and comonads in a single coherent system
  • • See how each abstraction handles exactly the problem it was designed for
  • • Understand the layered architecture of a functional interpreter
  • • Recognize the categorical structure underlying practical programming patterns
  • • Appreciate how Rust's type system enforces correctness at each layer
  • Code Example

    #![allow(clippy::all)]
    // Stub — awaiting conversion from OCaml source.

    Key Differences

    AspectRustOCaml
    Recursive typesBox<ExprF<Expr>>native recursive types
    Pattern matchingexhaustive, verboseexhaustive, concise
    Free monadtrait objectspolymorphic variants
    Lensexplicit get/set fnsrecord functional update
    Effectsenum + interpreterEffect library / algebraic effects
    Performancezero-cost abstractionsGC overhead, JIT optim

    The grand synthesis reveals the payoff of learning each abstraction individually: they compose cleanly, each handling one concern, and the Rust type system ensures each boundary is sound.

    OCaml Approach

    OCaml achieves the same architecture more concisely:

    type expr_f = Lit of float | Var of string | Add of 'r * 'r
                | Let of string * 'r * 'r | Lam of string * 'r | App of 'r * 'r
    
    (* Catamorphism via fold *)
    let rec eval env = function
      | Lit n -> Ok (Num n)
      | Var x -> List.assoc_opt x env |> Option.to_result ~none:(Printf.sprintf "Unbound: %s" x)
      | Add (l, r) -> ...
      | Let (name, v, b) -> eval env v >>= fun vv -> eval ((name, vv) :: env) b
      | Lam (p, b) -> Ok (Closure (p, b, env))
      | App (f, x) -> eval env f >>= function
          | Closure (p, b, ce) -> eval env x >>= fun xv -> eval ((p, xv) :: ce) b
          | _ -> Error "Not a function"
    

    OCaml's algebraic types, pattern matching, >>= operator, and lack of explicit boxing make the interpreter visually cleaner while carrying the same categorical structure.

    Full Source

    #![allow(clippy::all)]
    // Stub — awaiting conversion from OCaml source.

    Deep Comparison

    OCaml vs Rust: Grand Synthesis

    Overview

    See the example.rs and example.ml files for detailed implementations.

    Key Differences

    AspectOCamlRust
    Type systemHindley-MilnerOwnership + traits
    MemoryGCZero-cost abstractions
    MutabilityExplicit refmut keyword
    Error handlingOption/ResultResult<T, E>

    See README.md for detailed comparison.

    Exercises

  • Extend the interpreter with recursive let (letrec) using a Rc<RefCell<Option<Value>>> thunk for self-reference.
  • Add a type inference pass as a separate catamorphism that annotates the AST with Type using the Cofree pattern.
  • Replace the free monad effect system with an algebraic effect handler that supports resumable exceptions (use the delimited continuation pattern from example 196).
  • Add lenses for all fields of InterpreterState and compose them to build a transaction-style update that rolls back on error.
  • Implement a pretty-printer for the AST using an anamorphism (unfold) into a document algebra, then render via a second catamorphism over the document type.
  • Open Source Repos