Haskell (GHC 9.12)

This assessment applies the coupling account — coupling as access to a shared resource, and the coupling floor [1], [2] — and the knowledge-embodiment theorem [3]; the language is assessed against its official reference [4].

1 Assessment

This page assesses Haskell in five parts: core coupling — what the language’s own constructs force; ecosystem coupling — what the surrounding platform, tooling, and community cost; engineering readiness — whether the artifact can be reproduced, verified, observed, worked in quickly, connected to other languages, and governed openly; the profile — the unscored facts a score cannot express; and the scoring detail — the mechanism marks and the arithmetic behind every score. A ✅ bullet marks a construct that helps. A ⚠️ or ❌ bullet marks a cost; the scoring model does not price every cost named here.

Core coupling 76/100 · Ecosystem coupling 56/100 · Engineering readiness 53/100

1.1 Core coupling

1.1.1 Type

  • ✅ Pure functions separate side effects from pure logic: The type system (IO monad) keeps effects isolated, preventing hidden coupling to global state
  • ✅ Type classes enable polymorphism without inheritance coupling: Abstraction through type classes (Functor, Monad, etc.) decouples interface from implementation
  • ✅ Parametric polymorphism prevents coupling to concrete types: map :: (a -> b) -> [a] -> [b] works for any types without knowing their internals
  • ⚠️ Monad transformers can create coupling: Stacking monads (ReaderT, StateT, ExceptT) creates order-dependent coupling
  • ❌ IO monad couples all effects: Can’t separate file IO from network IO from randomness at type level (without effect systems)
  • ❌ Global type class instances couple: Orphan instances create action-at-a-distance coupling

1.1.2 Construction

  • ✅ Data constructors separate shape from creation logic: ADTs (Algebraic Data Types) decouple data structure from construction
  • ✅ Smart constructors enable validation without coupling: Can wrap raw constructors to add invariants
  • ✅ No shared mutable state: Construction doesn’t couple to global state

1.1.3 Memory

  • ✅ Garbage collection decouples memory from logic: Don’t think about deallocation
  • ✅ Immutability simplifies GC: No cyclic references from mutable structures
  • ⚠️ GC pauses couple to runtime: Non-deterministic pauses affect real-time requirements
  • ⚠️ Space leaks from lazy evaluation: Thunks accumulate, so evaluation strategy and computation order couple to memory usage
  • ✅ No manual memory management: Can’t have use-after-free or double-free bugs

1.1.4 Error

  • ✅ Either/Maybe separate success from failure: Either Error Result makes error path explicit and separate from success path
  • ✅ Exceptions are typed: IO exceptions are contained in IO monad, preventing hidden coupling
  • ⚠️ Partial functions (head, tail) can couple: Runtime errors bypass type system unless avoided

1.1.5 Concurrency

  • ✅ STM (Software Transactional Memory) decouples concurrency from logic: Composable transactions separate concurrent coordination from business logic
  • ✅ Immutability prevents temporal coupling: No shared mutable state means concurrent operations don’t interfere
  • ✅ Async/threading is explicit in types: Concurrency concerns are separate via type signatures

1.1.6 Platform

  • ✅ No vendor owns the language: The Haskell 2010 report is a community standard, and GHC — the de facto reference compiler — is open source under a permissive BSD-style licence
  • ✅ Native-code targets: GHC emits native executables for Linux, macOS, and Windows, so no virtual machine must be installed on the target host
  • ✅ Free, redistributable toolchain: GHC, Cabal, and Stack are open source and freely redistributable, with no vendor licence gate
  • ✅ Open package distribution: Hackage and Stackage index open-source packages under open licences, so dependencies are not gated by a vendor registry

1.1.7 Trade-offs (not coupling)

  • Performance vs. Abstraction: Lazy evaluation optimizes for composability but couples performance to evaluation strategy
  • Purity vs. Practicality: IO monad is all-or-nothing—can’t separate different IO types without mtl/effect systems
  • Type Class Coherence vs. Modularity: Only one instance per type globally couples modules that define instances
  • Laziness vs. Predictability: Space/time behavior depends on evaluation order, creating hidden coupling
  • Monad Transformer Order: ReaderT (StateT (ExceptT ...)) ≠ StateT (ReaderT (ExceptT ...)), order matters

1.2 Ecosystem coupling

1.2.1 Performance

  • ⚠️ Lazy evaluation couples performance to evaluation strategy: Space/time behavior is non-obvious, creating coupling between logic and performance
  • ⚠️ GC pauses unpredictable: Non-deterministic pauses couple timing-sensitive code to runtime behavior
  • ✅ Immutability enables parallelism: No data races, can parallelize without coupling to synchronization
  • ❌ Thunk accumulation: Space leaks couple memory usage to evaluation order

1.2.2 Ecosystem

  • ✅ Cabal/Stack standardized: Build system is consistent
  • ⚠️ Package ecosystem smaller than mainstream: Library availability couples to niche community
  • ✅ GHC is excellent: Compiler quality decouples from platform-specific quirks
  • ❌ Dependency hell with base library versions: Breaking changes couple code to GHC version

1.2.3 Evolution

  • ✅ GHC extensions allow gradual adoption: Can opt into new features without breaking existing code
  • ⚠️ Extensions create fragmentation: Different codebases use different language subsets
  • ✅ Haskell 2010 standard stable: Core language doesn’t break compatibility
  • ❌ Extension proliferation: Code couples to specific GHC versions and extension combinations

1.2.4 Domain

  • ✅ Excellent for parsers, compilers, DSLs: Type system supports these domains naturally
  • ⚠️ Struggles with I/O-heavy, stateful systems: IO monad creates friction for imperative domains
  • ❌ Poor for systems programming: GC, unpredictable performance couples to domain requirements
  • ✅ Strong for financial, formal verification: Correctness guarantees match domain needs

1.2.5 Learning

  • ❌ Very steep: Monads, functors, type classes couple productivity to deep expertise
  • ❌ Lazy evaluation surprises: Space leaks require expertise to debug
  • ✅ Excellent documentation: Books, tutorials decouple learning from trial-and-error
  • ⚠️ Multiple ways to do things: Mtl vs. transformers vs. effect systems couple to architectural choices

1.2.6 Syntax

  • ✅ Concise, expressive: Minimal boilerplate
  • ⚠️ Type signatures can be verbose: :: Monad m => (a -> m b) -> ... couples readability to type system knowledge
  • ✅ Function composition natural: f . g . h decouples steps
  • ❌ Operator overload: Custom operators (<$>, <*>, >>=) couple readability to library knowledge

1.2.7 Testing

  • ✅ QuickCheck property testing: Built-in support for generative testing
  • ✅ Pure functions easy to test: No setup/teardown coupling
  • ❌ Debugging lazy code hard: Stack traces don’t show evaluation order
  • ⚠️ GHCi debugger limited: Couples debugging to printf-style techniques

1.2.8 Security

  • ✅ Memory safe: GC prevents use-after-free, buffer overflows
  • ✅ Type safety prevents many bugs: Can’t mix incompatible types
  • ✅ Immutability prevents mutation bugs: No race conditions on shared state
  • ⚠️ Timing attacks possible: Lazy evaluation can leak information through timing

1.3 Engineering readiness

1.3.1 Reproducibility

  • ❌ Builds are not byte-reproducible by default.
  • ❌ Dependencies resolve without a lock by default.

1.3.2 Supply chain

  • ⚠️ Published packages carry no signed provenance by default.
  • ⚠️ The package registry is a flat name space.

1.3.3 Observability

  • ⚠️ No stable tracing and metrics standard.
  • ⚠️ The standard library has no structured logging.

1.3.4 Feedback

  • ❌ A change pays a slow build.

1.3.5 Interop

  • ✅ No charged mechanism in this dimension.

1.3.6 Governance

  • ✅ No charged mechanism in this dimension.

1.4 Profile

Unscored, and kept separate from every score on purpose. The profile records what a mechanism price cannot express: what a running program costs, how well a coding model and an agent work in the language, and whether a safety-critical path exists.

1.4.1 Energy and cost

What this axis asks: what does a running program cost in energy and time?

  • ✅ Compiles to native code: the fastest class in the language energy and time benchmarks [5], [6]. A causal re-analysis attributes the difference to execution time [7].

1.4.2 AI and agent readiness

What this axis asks: how well does a coding model and an agent work in this language?

  • ❌ Sparse training data: models write it unreliably [8].

1.4.3 Safety certification

What this axis asks: is there a certified or standards-qualified path to a safety-critical system?

  • ⚠️ No certified or standards-qualified path for safety-critical systems.

1.5 Scoring detail

1.5.1 Core coupling Dimensions

Dimension Mechanism Description Present Cost
Type T1 dynamic no static check — 0
T2 weak static — 0
T3 dynamic/duck dispatch — 0
T4 no sum types — 0
T5 no generics — 0
T6 no namespaces — 0
T7 type erasure/reflection — 0
T8 operator overloading ✅ −4
T9 inheritance required for polymorphism — 0
T10 no null-safety — 0
T11 no module boundary — 0
T12 no effect tracking — 0
T13 async/sync colouring — 0
T14 unchecked foreign boundary ✅ −4
Type subtotal −8
Construction C1 global mutable state by default — 0
C2 no immutability by default — 0
C3 constructors coupled to allocation — 0
C4 no constructor/validation — 0
Construction subtotal 0
Memory M1 manual deallocation — 0
M2 GC non-deterministic pauses ✅ −8
M3 no RAII ✅ −4
M4 no ownership model — 0
Memory subtotal −12
Error Er1 no structured path — 0
Er2 unchecked exceptions only — 0
Er3 errors ignored/non-exhaustive ✅ −4
Er4 no composable result type — 0
Error subtotal −4
Concurrency K1 GIL/no parallel — 0
K2 shared mutable state default — 0
K3 manual sync no race detection — 0
K4 no structured concurrency — 0
K5 no primitives — 0
Concurrency subtotal 0
Platform P1 cannot function outside one vendor/domain — 0
P2 single-vendor but other uses — 0
P3 legacy/discontinued platform — 0
Platform subtotal 0

Core Dimensions score: 76/100 — total cost = −24 (per-dimension subtotals are capped at −15; an uncapped cost is shown in parentheses where the cap bites).

1.5.2 Ecosystem coupling Dimensions

Dimension Mechanism Description Present Cost
Performance R1 interpreted no AOT/JIT — 0
R2 GC pauses ✅ −8
R3 JIT warmup — 0
Performance subtotal −8
Ecosystem Ec1 no package manager — 0
Ec2 fragmented tooling — 0
Ec3 small/niche/discontinued ✅ −8
Ec4 proprietary — 0
Ec5 platform-locked tooling — 0
Ec6 monoculture — 0
Ec7 legacy burden — 0
Ecosystem subtotal −8
Evolution V1 breaking changes ✅ −8
V2 frozen — 0
V3 discontinued — 0
V4 glacial standards — 0
Evolution subtotal −8
Domain D1 domain/vendor lock-in — 0
D2 poor domain fit — 0
D3 framework forces architecture — 0
Domain subtotal 0
Learning L1 steep ✅ −8
L2 large surface/multi-paradigm ✅ −4
L3 sparse docs — 0
Learning subtotal −12
Syntax S1 verbose — 0
S2 inconsistent — 0
S3 punctuation-heavy — 0
Syntax subtotal 0
Testing G1 weak tooling — 0
G2 poor debugging ✅ −8
G3 runtime-only errors — 0
Testing subtotal −8
Security Q1 memory-unsafe — 0
Q2 dynamic/weak typing risk — 0
Q3 known vulnerability/injection — 0
Security subtotal 0

Meta Dimensions score: 56/100 — total cost = −44 (per-dimension subtotals are capped at −15; an uncapped cost is shown in parentheses where the cap bites).

1.5.3 Engineering readiness Dimensions

Dimension Mechanism Description Present Cost
Reproducibility Y1 build not reproducible ✅ −8
Y2 dependencies not pinned ✅ −8
Reproducibility subtotal −15 (−16)
Supply chain Y3 no signed provenance ✅ −8
Y4 registry without namespacing ✅ −4
Supply chain subtotal −12
Observability Y5 no stable tracing standard ✅ −8
Y6 no structured logging ✅ −4
Observability subtotal −12
Feedback Y7 slow build ✅ −8
Y8 no fast in-editor analysis — 0
Feedback subtotal −8
Interop Y9 no foreign-function interface — 0
Y10 no portable target — 0
Interop subtotal 0
Governance Y11 single-vendor governance — 0
Y12 closed specification — 0
Governance subtotal 0

Readiness Dimensions score: 53/100 — total cost = −47 (per-dimension subtotals are capped at −15; an uncapped cost is shown in parentheses where the cap bites).

Verdict: Haskell’s type system detects and prevents coupling at compile time. Pure functions, explicit effects, and immutability make coupling visible and preventable. Main weaknesses: IO monad is too coarse-grained, lazy evaluation creates non-obvious coupling, monad transformers stack coupling.


The formal development. The definitions, theorems, and proofs behind this page are published in:

All published papers

References

[1]
Y. Loth, “On the nature of coupling: All coupling as shared resource access.” Zenodo, Aug. 2026. doi: 10.5281/zenodo.21925122.
[2]
Y. Loth, “Coupling as a consequence of cohesion: Decomposition, the coupling floor, and domain-imposed coupling.” Zenodo, Aug. 2026. doi: 10.5281/zenodo.21925201.
[3]
Y. Loth, “On the nature of cohesion: Cohesion as correctness relative to a partitioning rule.” Zenodo, Jul. 2026. doi: 10.5281/zenodo.21703193.
[4]
S. Peyton Jones and H. 2010. L. Committee, “Haskell 2010 language report.” Haskell, 2010. Available: https://www.haskell.org/onlinereport/haskell2010/
[5]
R. Pereira et al., “Energy efficiency across programming languages: How do energy, time, and memory relate?” in Proceedings of the 10th ACM SIGPLAN international conference on software language engineering (SLE), 2017, pp. 256–267. doi: 10.1145/3136014.3136031.
[6]
R. Pereira et al., “Ranking programming languages by energy efficiency,” Science of Computer Programming, 2021, doi: 10.1016/j.scico.2021.102609.
[7]
N. van Kempen, H.-J. Kwon, D. T. Nguyen, and E. D. Berger, “It’s not easy being green: On the energy efficiency of programming languages,” in Proceedings of the 40th IEEE/ACM international conference on automated software engineering (ASE), 2025. doi: 10.1109/ASE63991.2025.00131.
[8]
S. Joel, J. J. Wu, and F. H. Fard, “A survey on LLM-based code generation for low-resource and domain-specific programming languages,” ACM Transactions on Software Engineering and Methodology, 2025, doi: 10.1145/3770084.