BudiBadu Logo
Samplebadu

Haskell by Example: Pattern Matching

GHC 9.x

Deconstructing data with multiple function definitions through this code example showing pattern matching on literal values, list patterns for empty and non-empty cases, wildcard underscore for ignored values, and top-to-bottom pattern evaluation.

Code

-- Calculate factorial using pattern matching
factorial :: Integer -> Integer
factorial 0 = 1
factorial n = n * factorial (n - 1)

-- Describe a list
describeList :: [a] -> String
describeList [] = "The list is empty"
describeList [x] = "The list has one element"
describeList xs = "The list has many elements"

-- Custom data type matching
sayHello :: String -> String
sayHello "Alice" = "Hello, Alice!"
sayHello "Bob"   = "Hello, Bob!"
sayHello name    = "Hello, stranger!"

Explanation

Pattern matching in Haskell allows deconstructing data and executing different code paths based on the structure of input values. Instead of complex conditional statements, functions are defined with multiple equations, each handling a specific pattern of arguments. Patterns are checked sequentially from top to bottom, with the first matching pattern determining which equation executes.

Pattern matching capabilities include:

  • Literal value patterns match specific constants like 0, "Alice", or True
  • Variable patterns like n or name bind the entire value to that identifier
  • List patterns use [] for empty lists, [x] for singleton lists, (x:xs) for head and tail
  • Wildcard _ matches any value without binding it to a variable
  • Tuple patterns destructure fixed-size heterogeneous collections

Exhaustiveness checking by the Glasgow Haskell Compiler warns when patterns don't cover all possible inputs, preventing runtime errors from unhandled cases. The compiler flag -Wincomplete-patterns enables these warnings. Pattern matching is irrefutable when it cannot fail, such as variable patterns or wildcards, while refutable patterns like literal matches can fail if the value doesn't match.

Code Breakdown

3
factorial 0 = 1 base case matches literal zero value.
8
describeList [] matches empty list, [x] matches singleton.
10
xs variable pattern catches all remaining cases, binds value.
16
sayHello name catch-all pattern must be last, binds any unmatched string.