Pattern matching and guards are two essential features of Haskell that allow you to simplify and structure your code.
**Pattern matching** is the process of matching values against patterns, usually in function or case expressions, to deconstruct data structures and conditionally trigger according to the matched patterns. It provides an expressive and concise way to handle different cases of data structures in a type-safe manner.
**Guards** are boolean expressions that work as guards for pattern matches. They are introduced with the ‘|‘ symbol and allow refining patterns or recursive calls based on certain predicates. Guards provide a functional alternative to if-then-else expressions.
Here’s an example of a function that uses pattern matching and guards to calculate the absolute value of an integer:
absInt :: Int -> Int
absInt x
| x < 0 = -x
| otherwise = x
In this example, we first define a function ‘absInt‘ that takes an ‘Int‘ as input and returns an ‘Int‘ as output. We then use guards to pattern match on the input value ‘x‘. If ‘x < 0‘, we return the negation of ‘x‘ (i.e., ‘-x‘), which is the absolute value of a negative integer. If the guard ‘x < 0‘ is not satisfied, we proceed to the next guard: the ‘otherwise‘ keyword, which is just an alias for ‘True‘. Since it always evaluates to true, we simply return ‘x‘ as the absolute value of a non-negative integer.
Here’s another example that demonstrates both pattern matching and guards using the ‘factorial‘ function, which computes the factorial of a non-negative integer:
factorial :: Integer -> Integer
factorial 0 = 1
factorial n
| n > 0 = n * factorial (n - 1)
| otherwise = error "Negative input"
In this example, we first pattern match on the base case when the input is ‘0‘, returning ‘1‘. For other cases, we use guards to check if ‘n > 0‘. If true, we recursively call the ‘factorial‘ function with ‘n - 1‘ and multiply the result by ‘n‘. If the guard ‘n > 0‘ is not satisfied, it implies a negative input, so we use the ‘error‘ function to raise an error message.
In summary, pattern matching and guards are essential features in Haskell that allow you to define functions in a concise and expressive manner, providing elegant and type-safe ways to handle different cases of data structures.