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