Back to KB
Difficulty
Intermediate
Read Time
7 min

CLAUDE.md for Haskell: 13 Rules That Make AI Write Idiomatic, Type-Safe Haskell

By Codcompass TeamΒ·Β·7 min read

Haskell has the largest gap between code that compiles and code that's actually idiomatic of any mainstream language. The type system is powerful enough that AI can generate Haskell that type-checks but uses head on empty lists, catches errors with error "", and avoids the very abstractions that make Haskell valuable.

A CLAUDE.md at your project root tells the AI which Haskell you're writing. Here are 13 rules with the highest impact.


Rule 1: GHC version and language extensions

GHC version: 9.6+ (GHC2021 language set or explicit extensions).
Enable these extensions in package.yaml or cabal file (not per-file pragmas except for unusual cases):
  OverloadedStrings, ScopedTypeVariables, LambdaCase, TupleSections,
  DeriveFunctor, DeriveGeneric, GeneralizedNewtypeDeriving,
  FlexibleInstances, FlexibleContexts

Do NOT enable: PartialTypeSignatures (forces you to complete type signatures).
Do NOT use extensions that enable unsafe operations unless documented.

Enter fullscreen mode Exit fullscreen mode

GHC's language extension system is powerful but needs explicit guidance. AI sometimes adds extensions ad-hoc or omits ones that would enable cleaner code.


Rule 2: No partial functions β€” totality is the goal

Partial functions are banned:
- Never use `head`, `tail`, `init`, `last` β€” use pattern matching or `NonEmpty`
- Never use `fromJust` β€” use `maybe`, `fromMaybe`, or pattern match
- Never use `read` on untrusted input β€” use `readMaybe` from `Text.Read`
- Never use `error` for recoverable failures β€” use `Either` or `ExceptT`
- Never use `undefined` except as a temporary compile placeholder with a TODO comment

Prefer total alternatives:
  `headMay`, `atMay` from the `safe` package, or pattern matching.

Enter fullscreen mode Exit fullscreen mode

Partial functions are the #1 source of runtime crashes in Haskell. head [] throws an exception that the type system didn't catch. AI uses partial functions because they're shorter and common in tutorials.


Rule 3: Maybe and Either β€” explicit absence and failure

Absence and failure:
- `Maybe a` for values that may not exist
- `Either e a` for operations that can fail with an error
- `ExceptT e m a` for monadic computations that can fail
- `MaybeT m a` for monadic computations that may produce nothing

Chain with `>>=`, `<$>`, `<*>`, `maybe`, `either`, `fromMaybe`.
Never throw exceptions for business logic β€” use `Left err`.

For error types: define a sum type, not `String`:
  `data AppError = NotFound Text | InvalidInput Text | DatabaseError Text`

Enter fullscreen mode Exit fullscreen mode

error "something went wrong" is Haskell's equivalent of unchecked exceptions. The type system is there to make errors explicit β€” use it.


Rule 4: Type signatures on all top-level definitions

Every top-level function and value must have an expl

πŸŽ‰ Mid-Year Sale β€” Unlock Full Article

Base plan from just $4.99/mo or $49/yr

Sign in to read the full article and unlock all 635+ tutorials.

Sign In / Register β€” Start Free Trial

7-day free trial Β· Cancel anytime Β· 30-day money-back