Pattern Matching on Values

Introduction to Pattern Matching

Welcome to the very first unit of our seven-unit course! In the previous course, you learned how to make choices in your code using guards — asking yes-or-no math questions like x > 0. As we start this new course, we will explore a new, more structural way to make decisions called pattern matching.

Instead of asking logical questions, pattern matching allows you to define exactly what input values you expect to see. Think of it like a mail-sorting room where packages are routed based on reading exact labels. If the label matches perfectly, the package goes to a specific bin. This technique is a foundational part of Haskell, and today we will start by matching simple, literal values.

Defining Functions by Cases (Literal Matching)

In Haskell, you do not have to write a single, complex block of code to handle all inputs. Instead, you can define a function multiple times, providing one equation for each specific case.

Let's start building a function named describeDigit that takes an Int and returns its spelled-out name. We can write an equation that specifically matches the literal number 0:

Haskell
describeDigit :: Int -> String
describeDigit 0 = "zero"

In this code, instead of using a variable name like x, we literally placed the number 0 in the parameter spot. This tells Haskell exactly what to return when it sees a 0.

We can easily expand this by adding more equations for 1 and 2:

Haskell
describeDigit :: Int -> String
describeDigit 0 = "zero"
describeDigit 1 = "one"
describeDigit 2 = "two"

We can do the same thing with characters. Let's create an isVowel function. We want to return True if the input is a vowel. We simply write one equation for each vowel:

Haskell
isVowel :: Char -> Bool
isVowel 'a' = True
isVowel 'e' = True
isVowel 'i' = True
isVowel 'o' = True
isVowel 'u' = True

This structure makes your code very easy to read. Each equation names the exact shape of the input it expects to handle.

Catching Everything Else with the Wildcard (_)

You might be wondering: what happens if we give describeDigit the number 7, or if we give isVowel the letter 'z'? Right now, our program would crash because we did not give Haskell instructions for those specific values.

To fix this safely, we use the underscore symbol _. In Haskell, _ is known as the wildcard or catch-all pattern. It simply means "match absolutely anything."

Let's finish our describeDigit function by adding a _ equation at the end that returns "many":

Haskell
describeDigit :: Int -> String
describeDigit 0 = "zero"
describeDigit 1 = "one"
describeDigit 2 = "two"
describeDigit _ = "many"

Now, if we pass a 7 into this function, it bypasses 0, 1, and 2, and safely lands on the _, returning "many".

We can complete our isVowel function the exact same way. Any character that is not a designated vowel should return False:

Haskell
isVowel :: Char -> Bool
isVowel 'a' = True
isVowel 'e' = True
isVowel 'i' = True
isVowel 'o' = True
isVowel 'u' = True
isVowel _   = False
Sign up

Join the 1M+ learners on CodeSignal

Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal