Conditionals: if and Guards
Prerequisites: Defining functions
if-then-else is an expression
In Haskell, if produces a value, like the ? : operator in C-style
languages. That's why the else is required — the expression must
have a value either way:
describe :: Int -> String
describe n = if n < 0 then "negative" else "non-negative"
main :: IO ()
main = do
putStrLn (describe (-3))
putStrLn (describe 5)
print (if 10 > 3 then 1 else 0 + 100)
negative
non-negative
1
Both branches must have the same type — you can't return a String
from one and an Int from the other.
Guards
For more than two cases, guards read much better than nested ifs.
Each | is followed by a condition and the result if it's true, checked
top to bottom:
classify :: Int -> String
classify n
| n < 0 = "negative"
| n == 0 = "zero"
| n < 10 = "small"
| otherwise = "large"
bmi :: Double -> Double -> String
bmi weight height
| value < 18.5 = "underweight"
| value < 25 = "normal"
| otherwise = "overweight"
where
value = weight / height ^ 2
main :: IO ()
main = do
mapM_ (putStrLn . classify) [-5, 0, 7, 42]
putStrLn (bmi 70 1.75)
negative
zero
small
large
normal
otherwiseis simply defined asTrue— a catch-all final guard.wheredefines helper values that all guards can use (more on it in a later lesson).mapM_ f listruns an action for every element of a list.
Comparison and logic operators
| Operator | Meaning |
|---|---|
==, /= |
Equal, not equal (note /=, not !=) |
<, <=, >, >= |
Ordering |
&&, ` |
main :: IO ()
main = do
print (3 /= 4, not True, True && False || True)
print (compare 3 7, compare "b" "a", max "apple" "pear")
(True,False,True)
(LT,GT,"pear")
compare returns an Ordering: LT, EQ, or GT. Strings compare
alphabetically.
Practice
Write fizzbuzz :: Int -> String with guards and print it for 1 to 15
using mapM_.
Show solution
fizzbuzz :: Int -> String
fizzbuzz n
| n `mod` 15 == 0 = "FizzBuzz"
| n `mod` 3 == 0 = "Fizz"
| n `mod` 5 == 0 = "Buzz"
| otherwise = show n
main :: IO ()
main = mapM_ (putStrLn . fizzbuzz) [1 .. 15]
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz