Lesson 5 / 25
Pattern Matching, Guards and case
Define functions by cases on the shape of their arguments.
Matching on structure
Haskell functions are often defined by multiple equations, each with patterns on its arguments; the first matching equation is used. Patterns include literals (0), variables (n), the wildcard _, list patterns ([] and (x : xs)), tuples ((a, b)), data constructors (Just x, Left err) and as-patterns (all@(x : _)) that bind both the whole and its parts. Guards add boolean conditions to a pattern. The case ... of expression matches inside an expression. Patterns in lambdas and let bindings are allowed too. GHC's -Wall (which includes -Wincomplete-patterns) warns when a function does not handle every possible input, so you catch missing cases at compile time rather than with a runtime "non-exhaustive patterns" error. Pattern matching is lazy-friendly and efficient, and combined with algebraic data types it replaces most of the conditional logic you would write in other languages.
Patterns, guards and case
Lists, tuples, as-patterns and an exhaustive case.
describeList :: [a] -> String
describeList [] = "empty"
describeList [_] = "one element"
describeList [_, _] = "two elements"
describeList (_ : _) = "many elements"
-- as-pattern keeps the whole list while matching its head
firstAndAll :: Show a => [a] -> String
firstAndAll [] = "nothing"
firstAndAll all'@(x : _) = "first " ++ show x ++ " of " ++ show (length all')
classify :: Int -> String
classify n
| n < 0 = "negative"
| n == 0 = "zero"
| even n = "positive even"
| otherwise = "positive odd"
orderStatus :: (String, Int) -> String
orderStatus order =
case order of
(sku, 0) -> sku ++ ": out of stock"
(sku, qty)
| qty < 5 -> sku ++ ": only " ++ show qty ++ " left"
| otherwise -> sku ++ ": in stock"
main :: IO ()
main = do
putStrLn (describeList "abc") -- many elements
putStrLn (firstAndAll [10, 20, 30 :: Int]) -- first 10 of 3
mapM_ (putStrLn . classify) [-3, 0, 4, 7]
putStrLn (orderStatus ("pen", 3)) -- pen: only 3 leftA mail sorter
Each equation is a slot in a mail sorter: an envelope goes into the first slot whose shape it fits. -Wall is the supervisor who points out envelope shapes that have no slot at all.
Quick check: What does GHC's -Wincomplete-patterns warning (part of -Wall) catch?
- Slow code
- Functions or case expressions that do not handle every possible input
- Unused imports only
- Type errors
Answer
Functions or case expressions that do not handle every possible input — It reports missing cases at compile time.