Pattern Matching
Every function written since haskell1-4 has already used pattern matching, informally — sumList's []/(x:xs) equations, haskell1-6's own next. This chapter formalizes it, and traces the real lineage to Rust's match and C#'s own switch patterns.
Matching on Constructors
Multiple function equations are pattern matching — each one matches a specific constructor shape, tried top to bottom until one succeeds. This has been in use since Chapter 4 without being named.
case Expressions
case is the explicit, single-expression form of what multiple top-level equations do implicitly — useful when pattern matching is only part of a function body, not the whole thing.
Guards
A guard (| condition) adds a boolean condition on top of a successful pattern match. This is the direct conceptual ancestor of C#'s own when clause in csharp2-5's switch patterns, and Rust's own match guards — Haskell had this decades before either.
As-Patterns
all@(x:_) binds the entire matched value to all while also binding its parts (x) separately — using both the pieces and the whole without re-matching or reconstructing anything. A genuinely nice convenience with no exact equivalent named in either Rust's or C#'s own pattern syntax on this site.
Exhaustiveness Checking
GHC can warn — and, with a flag, hard-error — when a set of patterns doesn't cover every constructor of a type. Name this plainly: Haskell's pattern matching was exhaustiveness-checked long before rust1-6's own match or csharp2-7's own exhaustive switch over sealed types existed. Both of those are, in a real sense, downstream of this exact idea.
Nested Patterns
Patterns nest arbitrarily deep — matching straight into a Maybe (Tree a) in one shot, with no chain of manual unwrapping required.
| Feature | Rust match | C# switch (csharp2-5) | Haskell — the origin |
|---|---|---|---|
| Exhaustiveness enforcement | yes, compile error | yes, over sealed types | warning by default, error with a flag — decades earlier |
| Guards | match guards | when clause | | guard — the real ancestor of both |
| Bind whole + parts at once | @ bindings, similar spirit | not directly available | as-patterns (x@pattern) |
-Wincomplete-patterns (and -Werror=incomplete-patterns to make it fail the build) catches a missing case at compile time — the same safety Rust's compiler-enforced exhaustiveness gives by default, opt-in but genuinely worth enabling on every project.
"Non-exhaustive patterns" — a genuine runtime crash, not something GHC's own compile-time warning catches automatically unless it's explicitly promoted to a hard error.
Coding Challenges
Write a function grade :: Int -> String using guards that returns "A", "B", "C", or "F" based on a numeric score, with otherwise as the final fallback.
📄 View solutionWrite a function summarizeList :: [Int] -> String using an as-pattern that returns a string mentioning both the full list and its first element, for a non-empty list, and a distinct message for the empty list.
📄 View solutionWrite a function over the Shape type from haskell1-6 that deliberately omits one constructor's pattern, compile it with -Wincomplete-patterns, and report the resulting warning text. Then fix it.
📄 View solutionChapter 7 Quick Reference
- Multiple function equations ARE pattern matching, already in use since Chapter 4; case expresses the same idea in one spot
- Guards (| condition) add a boolean check on top of a pattern — the real ancestor of Rust's match guards and C#'s own when clause
- As-patterns (x@pattern) bind the whole value and its parts simultaneously — no direct equivalent named for Rust or C# on this site
- Exhaustiveness checking predates rust1-6's match and csharp2-7's sealed-type switch by decades — both are downstream of this idea
- Patterns nest arbitrarily deep, avoiding manual unwrapping chains
- -Wincomplete-patterns (or -Werror=incomplete-patterns) catches a missing case at compile time; without it, a reached incomplete match crashes at runtime
- Next chapter: typeclasses, a first look — the real ancestor of rust2-2's own traits, arriving decades earlier