While if/else
expressions can be used to execute conditional logic, Haskell also has a more powerful way to execute conditional logic: pattern matching.
With pattern matching, a value can be tested against one or more patterns.
An example of such a pattern is the constant pattern, which matches a value against a constant (e.g. 1
or "hello"
).
When defining functions, you can define separate function bodies for different patterns. This leads to clean code that is simple and readable. You can pattern match on any data type β numbers, characters, lists, tuples, etc.
For example, a trivial function that takes a whole number (Int
) and makes it 1 closer to 0 could be expressed like this:
closerToZero :: Int -> Int
closerToZero 0 = 0
closerToZero 1 = 0
Pattern matching starts to shine when used together with other patterns, for example the variable pattern:
closerToZero :: Int -> Int
closerToZero 0 = 0
closerToZero n = n - 1
The above example treats all inputs other than 0 the same, and would produce incorrect results for negative numbers.
This can be solved using conditional patterns, known as guards, which are expressed with the |
symbol:
closerToZero :: Int -> Int
closerToZero n
| n < 0 = n + 1
| n > 0 = n - 1
In the above examples not all possible inputs have a matching pattern.
The compiler will detect this and output a warning.
This is a very useful feature of Haskell that helps ensure all possible paths are covered to avoid run-time errors.
It is known as exhaustive checking.
To solve the warning, you have to handle all cases.
Within guards you can use the expression otherwise
as syntactic sugar for True
to catch all remaining patterns.
closerToZero :: Int -> Int
closerToZero n
| n < 0 = n + 1
| n > 0 = n - 1
| otherwise = 0
Pattern matching will test a value against each pattern from top to bottom, until it finds a matching pattern and executes the logic associated with that pattern. The order of patterns matters!
In this exercise, you are playing a number guessing game with a friend.
The rules are simple: you secretly choose a number between 1
and 100
and your friend tries to guess what number you've chosen.
To help your friend, you respond differently depending on how close the guess was to the number you've chosen (42
).
These are the rules for the different possible inputs:
42
: "Correct"41
or 43
: "So close"41
: "Too low"43
: "Too high"You have four tasks to encode the replies to the guesses.
Implement the reply
function to reply to a correct guess:
reply 42
-- -> "Correct"
Modify the reply
function to reply to close guesses:
reply 41
-- -> "So close"
Modify the reply
function to reply to too low guesses:
reply 25
-- -> "Too low"
Modify the reply
function to reply to too high guesses:
reply 88
-- -> "Too high"
Sign up to Exercism to learn and master Haskell with 107 exercises, and real human mentoring, all for free.