- Basic Pattern Matching
- Pattern matching with tuples
- Pattern Matching with lists
- Binding to names
Basic Pattern Matching
When defining functions in Haskell, we can define separate function bodies for different patterns.
luckySeven :: (Integral a) => a -> String luckySeven 7 = "Today's your lucky day." luckySeven x = "Not your lucky day."
When we call a function like this, we check the patterns from top to bottom and once we find the match we use that particular function body.
Factorial with pattern matching:
factorial' :: (Integral a) => a -> a factorial' 0 = 1 factorial' n = n * factorial' (n - 1)
This is a common paradigm used in Haskell for recursion. Specifically define for edge cases and then write your base case.
Pattern matching can fail if we do not match any function body for the given input. For example:
λ> say 1 = "One" λ> sayOne 1 1 λ> sayOne 2 *** Exception: <interactive>:46:1-12: Non-exhaustive patterns in function sayOne
Pattern matching with tuples
Pattern matching can also be used in tuples. For example vector addition:
addVectors :: (Num a) => (a, a) -> (a, a) -> (a, a) accVectors (x1, y1) (x2, y2) = (x1 + x2, y1 + y 2)
snd get first and second elements of tuple pairs. What if we want for triplets.
fst' :: (a, b, c) -> a fst' (x, _, _) = x snd' :: (a, b, c) -> a snd' (_, y, _) = y thr' :: (a, b, c) -> a thr' (_, _, z) = z
_ means that the value exists but has no meaning for our function so we don’t use it.
As a side note, we can also pattern match in list comprehenshion.
λ: let pairs = [("Horse", "Mare"), ("Lion", "Lioness"), ("Fox", "Vixen")] λ: [a ++ " and " ++ b | (a, b) <- pairs] ["Horse and Mare","Lion and Lioness","Fox and Vixen"]
Pattern Matching with lists
Lists can also be used for pattern matching. They can match with empty list, or any pattern that involves
: and an empty list. Effectively,
[1,2,3] is just
sayWhenOneTwoThree :: (Num a, Eq a) => [a] -> String sayWhenOneTwoThree [1, 2, 3] = "One! Two! Three!" sayWhenOneTwoThree _ = "Nothing to say"
λ: sayWhenOneTwoThree [1,2,3] "One! Two! Three!" λ: sayWhenOneTwoThree  "Nothing to say"
head' :: [a] -> a head'  = error "No head can be found for empty list" head' (x:xs) = x
λ: head' [9, 12, 2] 9 λ: head' [12, 2] 12
x:xs pattern is used a lot in context of recursive functions. The first part
x will be the element and
xs will be the rest of the list.
It can be used for first n elements:
sayElement :: (Show a) => [a] -> String sayElement  = "Empty list" sayElement (x:) = "One element only that is: " ++ show x sayElement (x:y:) = "Two elements, those are: " ++ show x ++ " and " ++ show y sayElement (x:y:xs) = "More than two elements. First two are: " ++ show x ++ " and " ++ show y ++ " and rest: " ++ show xs
length' :: [a] -> Int length'  = 0 length' (x:xs) = 1 + length' xs
sum' :: (Num a) => [a] -> a sum'  = 0 sum' (x:xs) = x + sum' xs
Binding to names
We can also break something up according to a pattern and binding to names, while still keeping reference to the whole thing. We can do that by using
@ in front of the pattern.
firstLetter:: String -> String firstLetter  = "Empty string!" firstLetter [email protected](x:xs) = "The first letter for " ++ w ++ " is " ++ [x] ++ " while the rest is: " ++ xs
λ: firstLetter "2001 : Year" "The first letter for 2001 : Year is 2 while the rest is: 001 : Year"