Guarded equations for conditional expressions in Haskell
Conditional expressions are fundamental programming constructs to choose a sub-expression based on a logical condition. if e then e1 else e2
is the most common syntax to accomplish this. Here e
is the logical expression and the entire expression evaluates to e1
if e
evaluates to True
and e2
if e
evaluates to False
. Although semantically simple, it becomes hard to read for nested conditionals. For example, for a function to calculate discount based on the number of items purchased per the table below, we can write our code as follows:
# of items | Discount |
---|---|
> 100 | 0.20 |
> 50 | 0.10 |
> 20 | 0.05 |
otherwise | 0 |
getDiscount :: Fractional a => Int -> a
getDiscount n =
if n > 100
then 0.20
else if n > 50
then 0.10
else if n > 20
then 0.05
else 0
Haskell provides an alternative syntax called guarded equations to make nested conditionals more concise and readable. Syntax is
f x | b1 = e1
| b2 = e2
...
Here bi
is a boolean expression which if evaluates to True
, the entire function's result will be the result of evaluating ei
. An optional catch all phrase is otherwise
which is equivalent to True
and thus is used for conditional in case every expression above it evaluates to False
. It is used at the end of guarded equation. Let's see how our example above translated to guarded equation.
getDiscount2 :: Fractional a => Int -> a
getDiscount2 n | n > 100 = 0.20
| n > 50 = 0.10
| n > 20 = 0.05
| otherwise = 0
Much better!