Reducing Lists with Fold
Introduction: Crushing a List into One Value
Welcome to the fifth unit of our course! In the previous lessons, you learned how to treat functions as values and apply them using tools like map to transform lists and filter to select specific items. However, another common task in programming is taking a list of many items and collapsing it into a single value.
Whether you need to find the sum of a list of numbers, identify the largest number, or simply count how many items it contains, you are performing a reduction. In this lesson, we will explore folds, which are Haskell's elegant, built-in tools for reducing lists automatically.
Recall: The Accumulator Pattern
Before we introduce our new tools, let us take a moment to recall a concept from Course 2. You might remember writing manual recursion to process a list using an accumulator pattern.
An accumulator pattern involves a starting value (often called a seed, like 0) that is updated step-by-step as you traverse a list. For example, to sum a list, you started with 0, added the first number to it, then added the second number to that new total, and so on until the list was empty.
A fold is simply this exact seed-and-update pattern wrapped in a convenient higher-order function. Instead of writing out manual recursion every time, you can let Haskell handle the repetition for you.
Summing Lists with foldl
Let us learn how to use our first folding function: foldl (which stands for "fold left"). Here is its type signature:
This tells us that foldl takes a combining function, a starting accumulator value, and a list. The combining function receives the current accumulator first and the current list item second, then returns the next accumulator.
Let us start by defining a value called total and providing foldl with its combining function and starting value.
Here, (+) is our combining function. We place it in parentheses to pass the addition operator as a function. The 0 is our starting accumulator value.
Next, we provide the list of numbers we want to reduce.
When you run this code, the output will be:
15
Behind the scenes, foldl takes the starting 0 and adds the first element 1 to get 1. It then takes that 1 and adds the next element 2 to get 3, continuing this process from left to right until the entire list is consumed and reduced to 15.
For small examples, foldl is fine for learning. In real programs with very large lists and strict numeric accumulators, foldl' from Data.List is often preferred because it avoids building up too much lazy accumulator work.
