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.