ExamplesBy LevelBy TopicLearning Paths
192 Expert

Effects as State

Functional Programming

Tutorial Video

Text description (accessibility)

This video demonstrates the "Effects as State" functional Rust example. Difficulty level: Expert. Key concepts covered: Functional Programming. The state monad is a functional pattern for threading state through a computation without explicit mutable state. Key difference from OCaml: 1. **Native vs. simulated**: OCaml's effect

Tutorial

The Problem

The state monad is a functional pattern for threading state through a computation without explicit mutable state. The effect-based equivalent provides Get and Put effects that a handler satisfies by threading state. This unifies state management with the effect handler model, enabling stateful computations to be tested with different initial states, logged, and combined with other effects — all without modifying the computation itself.

🎯 Learning Outcomes

  • • Implement Get and Put as algebraic effects satisfied by a state handler
  • • Compare effect-based state with the state monad and with explicit &mut passing
  • • See how swapping state handlers enables different state management strategies
  • • Understand how state effects compose with other effects in a handler stack
  • Code Example

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

    Key Differences

  • Native vs. simulated: OCaml's effect-based state runs at near-native speed; Rust's simulation has closure/heap overhead.
  • Isolation: OCaml's handler encapsulates the ref cell — the program cannot access it directly; Rust's simulation must structure the callbacks carefully to prevent state leakage.
  • Composition with other effects: OCaml's nested handlers compose state with logging or exceptions naturally; Rust's simulation requires explicit effect routing.
  • Practical alternative: In Rust, &mut State passed through functions is the production idiom; effects are educational/advanced-pattern territory.
  • OCaml Approach

    OCaml 5 native state effects:

    effect Get : int
    effect Put : int -> unit
    let with_state initial f =
      let state = ref initial in
      match_with f () {
        effc = fun (type a) (e : a eff) ->
          match e with
          | Get -> Some (fun k -> continue k !state)
          | Put v -> Some (fun k -> state := v; continue k ())
          | _ -> None }
    

    The ref is local to the handler — the program itself has no access to mutable state.

    Full Source

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

    Deep Comparison

    OCaml vs Rust: Effect State

    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

  • Implement a with_pure_state handler that uses an immutable value thread instead of ref.
  • Add a Modify(f: impl Fn(S) -> S) effect that atomically applies a function to the state.
  • Compose state and logging: a handler that logs every Get and Put operation while also managing the state.
  • Open Source Repos