Skip to content

Pattern Matching

The case expression is useful, but Haskell programmers use it fairly infrequently, because the following definition of our sign function is 100% equivalent:

sign :: Int -> Int
sign 0 = 0
sign x = if x > 0 then 1 else -1

By "100% equivalent", I mean that the compiler translates this into a single function definition using a case expression:

sign :: Int -> Int
sign z = case z of
    0 -> 0
    x -> if x > 0 then 1 else -1

This is exactly the implementation of the sign function we had at the beginning of the previous section, just using different variable names.

You can read the definition

sign :: Int -> Int
sign 0 = 0
sign x = if x > 0 then 1 else -1
quite naturally. It says that the sign of 0 is 0: sign 0 = 0. For any other value x, we have sign x = 1 if x > 0, and sign x = -1 otherwise. In the same way that your program inspects the branches of a case expression one at a time to find the one that matches the argument given to the case expression, when defining a function using multiple equations, these equations are inspected one at a time and the first one that matches the arguments provided to the function call is used. Just as in a case expression, the function arguments are patterns. Here, the pattern 0 matches only if we call sign with an argument that is actually 0. The pattern x in the second equation sign x = ... matches any argument and in the process, x is bound to the argument of sign and can then be referred to on the right-hand side of the equation.

Don't mistake the brevity of this subsection as meaning that function definitions using multiple equations and pattern matching are not important. They are in fact the most commonly used tool to implement case distinctions in Haskell because they lead to very readable code. It is just that there is not much to be said about defining functions this way, given that a definition of a function using multiple equations is 100% equivalent to a case expression, which we discussed in the previous section.