# Pattern Matching, Guards and case — Haskell

Source: https://www.geekswithgeeks.com/en/haskell/c-patterns

> 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.

```haskell
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 left
```

## A 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.

**Quiz:** What does GHC's -Wincomplete-patterns warning (part of -Wall) catch?

- [ ] Slow code
- [x] 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.
