Pattern matching limits us to performing fixed tests of a value’s shape. Although this is useful, we will often want to make a more expressive check before evaluating a function’s body. Haskell provides a feature called guards that give us this ability. We’ll introduce the idea with a modification of the function we wrote to compare two nodes of a tree:
-- file: ch03/BadTree.hs nodesAreSame (Node a _ _) (Node b _ _) | a == b = Just a nodesAreSame _ _ = Nothing
In this example, we use pattern matching to ensure that we are looking at values of the right shape, and a guard to compare pieces of them.
A pattern can be followed by zero or more
guards, each an expression of type
Bool. A guard is
introduced by a
| symbol. This is followed by the guard
expression, then an
= symbol (or
we’re in a
case expression), then the
body to use if the guard expression evaluates to
True. If a
pattern matches, each guard associated with that pattern is evaluated in
the order in which they are written. If a guard succeeds, the body
affiliated with it is used as the result of the function. If no guard
succeeds, pattern matching moves on to the next pattern.
When a guard expression is evaluated, all of the variables mentioned in the pattern with which it is associated are bound and can be used.
Here is a reworked version of our
lend function that uses
-- file: ch03/Lending.hs lend3 amount balance | amount <= 0 = Nothing | amount > reserve * 0.5 = Nothing | otherwise ...