Recursion Over Lists
Introduction To Recursion
Welcome to **Unit 6**! In the previous lesson, we explored how to generate and transform lists using **list comprehensions**. Now, we will look at how to process those lists step by step.
In many programming languages, you process lists using for or while loops. However, **Haskell** does not have loop structures. Instead, it relies on a concept called recursion. Recursion simply means that a function calls itself to repeat work.
You can think of recursion as eating a box of chocolates. You take one piece out (handling the current item), and you are left with a slightly smaller box of chocolates. You repeat this exact process on the smaller box until the box is completely empty. In this lesson, we will learn how to write our own **recursive functions** to process lists piece by piece.
Brief Recall: List Pattern Matching
Before we write our first recursive function, let us quickly recall how we pull lists apart. We first saw this in Unit 3 when we learned how to match patterns safely.
When working with lists, we usually care about two specific patterns:
[]: The empty list. This means there is nothing left to process.(x:xs): A non-empty list. Thexrepresents the head (the first item), and thexsrepresents the tail (the rest of the list).
In recursion, these two patterns act as our blueprint. The empty list [] becomes our stopping point, which we call the base case. The non-empty list (x:xs) is where we do our work and call the function again, which we call the recursive case.
Summing A List
Let us build our first recursive function step by step. Our goal is to create a function named **sumList** that adds up all the numbers in a list of **Int** integers.
First, we need to define our type signature and our base case. The base case tells the function when to stop. If we try to sum an empty list, the result should be 0.
By telling Haskell what to do with an empty list, we prevent the function from trying to repeat indefinitely.
Next, we add our recursive case to handle lists that actually contain numbers.
In the second equation, we use the (x:xs) pattern. We take the first number x and add it to the result of calling sumList on the rest of the list xs. This shrinks the list by one element every time it runs.
To see how this works in action, let us write out a small visual trace of what happens when we call sumList [1, 2, 3]:
sumList [1, 2, 3]becomes1 + sumList [2, 3]sumList [2, 3]becomes2 + sumList [3]sumList [3]becomes3 + sumList []sumList []hits our base case and becomes0- The final math is
1 + 2 + 3 + 0, which equals6.
Here is the complete code running inside a main function:
Output:
