Concurrency in Haskell: Fast, Simple, Correct
Haskell’s concurrency model and STM
- Commenters highlight how small and readable the
asyncandTQueueAPIs 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 inatomically, 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-containersuse 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
asynciois 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, andIOform 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 adoesn’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).