Haskell: A Great Procedural Language

Real‑world Haskell usage

  • Many commenters list substantial Haskell software: ImplicitCAD, ShellCheck, Pandoc, SimpleX Chat (core library), Wire server backend, xmonad/waymonad, hledger, PostgREST, Hasura (pre‑rewrite), Cardano components, and various CAD/music tools.
  • Multiple companies reportedly run significant Haskell backends (e.g., banking, retail, security, astrology SaaS); some use Haskell for almost all new backend code.
  • Haskell is seen as surprisingly strong for backend HTTP APIs, with frameworks like Servant (type‑level API descriptions, OpenAPI generation) highlighted.
  • There is also an “exhaustive list of Haskell in industry,” which some see as evidence of relatively small adoption.

Type system, monads, and syntax

  • Operators like >>=, >>, <*>, <*, *>, and <|> are a recurring pain point; people often favor do‑notation to improve readability, especially for newcomers.
  • Others learned monads via >>= and mentally “desugar” do; they see symbolic operators as conceptually simpler.
  • The map/fmap/traverse hierarchy and Traversable deriving are praised as extremely powerful abstractions that reduce boilerplate.
  • There is debate over “illegal states unrepresentable”: some argue Haskell makes many invalid states impossible, others note numeric and floating‑point domains remain tricky and less well‑supported than in Ada or dependently‑typed languages.

Effect systems, IO, and “procedural” style

  • Several argue Haskell makes imperative code better: IO and other effects are explicit in types, can be composed as first‑class values, and can be structured with strong monads and do‑notation to look procedural.
  • Others say real‑world IO code becomes complex when combined with other monads; effect systems (e.g., effectful, Bluefin) are recommended over classic monad transformer stacks.
  • Comparisons are drawn between IO and Promises/async‑await in JavaScript: both represent effectful computations chained monadically, but Haskell enforces a strong separation between pure and impure code.

Critiques, complexity, and adoption barriers

  • Complaints about “cruft” and inconsistency: historic standard library warts (head partial, map only for lists, lazy IO, exceptions, n+k patterns), proliferation of GHC extensions, and idiosyncratic DSLs per project.
  • Some feel this makes cross‑project work and onboarding hard; others note newer language profiles (GHC2021/GHC2024) and alternative preludes improve the baseline.
  • Tooling, confusing error messages, performance unpredictability, laziness‑related space leaks, and difficulties with debugging/state monads are cited as practical obstacles, though some say these are increasingly mitigated.
  • There is tension between claims that Haskell is “simple but unfamiliar” and the reality that many programmers struggle with its abstract type system and non‑imperative defaults.