# Haskell: Pattern Matching & Recursion¶

Note

These slides are also available in PDF format: 4:3 PDF, 16:9 PDF, 16:10 PDF.

## Learning Group Activity¶

1. Where did you make use of type variables and typeclasses?
2. Were your declarations ever too restrictive for the problem? Or too broad?

I will go around and check off your LGA. Have any questions for me? Homework questions? Also feel free to ask your group on HW questions.

## Pattern Matching¶

In Haskell, when you write multiple function bodies, the body that matches first gets called. For example:

hungryNumber :: (Integral a) => a -> String
hungryNumber 7 = "Eats nine"
hungryNumber 9 = "Gets eaten by seven"
hungryNumber n = "Does not eat other numbers"


## Recursion using Pattern Matching¶

One excellent use for pattern matching: recursion.

factorial :: (Integral a) => a -> a
factorial 0 = 1
factorial n = n * factorial (n - 1)


## Pattern Matching Tuples¶

A tuple with variables in a pattern match will assign names to each element.

addVectors :: (Num a) => (a, a) -> (a, a) -> (a, a)
addVectors (x1, y1) (x2, y2) = (x1 + x2, y1 + y2)


## Pattern Matching Lists¶

To match the empty list, use an empty list as the pattern:

hasStuff :: [a] -> Bool
hasStuff [] = False
hasStuff xs = True


## Deconstruction Pattern¶

Use (x:xs) as a pattern to:

• Match a list with one or more element
• Get the head of the list as x
• Get the tail of the list as xs

The names x and xs are arbitrary, but common.

Example:

head' :: [a] -> a


## Deconstruction & Recursion: Map Example¶

map' :: (a -> b) -> [a] -> [b]
map' _ [] = []
map' f (x:xs) = f x : map' f xs


## Patterns in List Comprehensions¶

Patterns can be placed into the RHS of a list comprehension:

-- uses an input like [(1, 2), (3, 4)]
addPairs :: (Num a) => [(a, a)] => [a]
addPairs xs = [a + b | (a, b) <- xs]


Similarly, you can use an (x:xs) pattern:

-- uses an input like [[1, 3], [4]]
tails :: [[a]] -> [[a]]
tails xs = [ys | (y:ys) <- xs]


Of course, this could have been written much more expressive as

tails = map tail


## As-Patterns¶

When the whole value of a pattern is desired, as well as the decomposed names, the @ symbol can be used to create an alias.

firstLetter :: String -> String
firstLetter word@(x:_) = "The first letter of "
++ word ++ " is " + [x]