Concurrency in Haskell: Fast, Simple, Correct

Haskell’s concurrency model and STM

  • Commenters highlight how small and readable the async and TQueue APIs are; much of the sophistication lives in the runtime (green threads, GC, STM engine).
  • STM (TVar, TQueue, etc.) is framed as conceptually like database transactions: operations run in atomically, changes go to a log, conflicts cause rollback and retry.
  • TVars are explicitly contrasted with mutexes: they “lock data, not code,” giving atomic, composable state changes without explicit lock/unlock and with nicer reasoning about invariants.
  • Libraries like stm-containers use TVars at tree nodes to reduce contention to O(log n) “spines” instead of whole structures.

Comparisons with other languages (Rust, Clojure, Scala, Python, BEAM)

  • Clojure and Scala are mentioned as also having STM, but with worse composability or weaker ecosystem uptake; in Clojure, atoms (CAS) are used far more than full STM refs.
  • Rust concurrency discussion centers on Arc<Mutex<T>> vs STM: Rust enforces “no aliasing while mutating” and forces locks for multi-writer state, giving strong memory safety but not transactional semantics.
  • Debate arises whether Rust’s model is sufficient vs STM’s ability to express multi-variable invariants (e.g., bank-account examples) without locks and deadlocks.
  • Python’s asyncio is widely criticized as fragile and footgun-prone; some compare more favorably to Clojure/Erlang/Elixir where immutability and lightweight processes are first-class.
  • Erlang/BEAM and Haskell are both cited as successfully using green threads and immutable data to handle large numbers of web requests.

Immutability, performance, and web servers

  • A concern that immutable structures mean “large allocations” is pushed back on: persistent data structures share structure and only copy O(log n) paths, not entire collections.
  • Haskell’s GC and allocation patterns are said to work well for short-lived web requests; Warp is cited as a high-performance Haskell HTTP server.
  • Some note Haskell’s memory use comes more from boxing and laziness than immutability per se.

Developer experience: strengths and warts

  • Enthusiasm for static types, algebraic data types, and refactorability (changing a type and letting the compiler guide all required changes).
  • Frictions mentioned: proliferation of string types, cryptic GHC errors vs Elm, unsafe stdlib functions like head, confusion over preludes and tooling (stack, cabal, ghcup, HLS).
  • STM and IO are described as “colored functions” in practice: pure, STM, and IO form tiers with clear call-direction rules, which is seen as key to STM’s safety.

Correctness claims and missing pieces

  • One commenter argues that IO a doesn’t encode concurrency structure, so “correct” in the title is limited; concurrency behavior remains a black box at the type level.
  • Others point out the article calls STM “fast” without showing benchmarks or a framework for reasoning about STM performance (contention, transaction length, retry costs).