Easier to read with cream paper, a tint, more contrast or larger text? Choose your colours and text, once, for every page.

Free lesson

Map, filter and fold

After this lesson: I can replace a loop over a list with map, filter or fold.

60 min lesson9 commandsHaskell lab: functional programming with functions and types, in the browser

How do map, filter and fold replace loops?

Map, filter and fold are three functions that do the job of most loops over a list. Map changes every item, filter keeps some of the items, and fold boils a list down to one value.

They matter because three short words can replace a long loop, and you can read what each one does at a glance. In this lesson you apply them to the prices in a shop.

By the end of this lesson

Note

I can replace a loop over a list with map, filter or fold.

Key words

WordWhat it means
Mapapply a function to every item of a list
Filterkeep only the items that pass a test
Foldcombine all the items of a list into one value
Higher-order functiona function that takes another function as an argument
Accumulatorthe running result that a fold carries along

The cells students fill in are left blank in this preview.

Map applies a function to every item

A shop adds a 50 pence delivery fee to each price. In a loop you make a new list and add each answer to it. With map you say just two things: which function, and which list.

The part (+ 50) is a function waiting for one number. It adds 50 to whatever it is given. Map hands it every price in turn.

Try it: the loop that map replaces

Code: python
def add_fee(price):
    return price + 50

prices = [1000, 2500, 400]
with_fee = []
for price in prices:
    with_fee.append(add_fee(price))
print(with_fee)
# Change add_fee so that it takes 10 off instead.
# Press Run. The loop stayed the same, only the function changed.

Add 50 to every price with map

Command
docker exec haskell ghc -e "map (+ 50) [1000, 2500, 400]"

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Ask GHC for the type of map

Command
docker exec haskell ghc -e ":type map"

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Filter keeps the items that pass a test

Now the shop wants only the prices above 500. The test (> 500) is a function that answers True or False. Filter keeps the items for which the test says True.

The answer can be shorter than the list you gave. If nothing passes, it is the empty list.

Keep the prices above 500

Command
docker exec haskell ghc -e "filter (> 500) [1000, 250, 700, 90]"

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Keep the even numbers

Command
docker exec haskell ghc -e "filter even [1, 2, 3, 4, 5, 6]"

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Fold combines a list into one value

A fold walks along a list and carries a running result, the accumulator. You give it three things: a function that combines two values, a start value, and the list.

foldr (+) 0 [10, 20, 30] starts at 0 and adds the items. The start value is also the answer for an empty list.

Add up three prices with a fold

Command
docker exec haskell ghc -e "foldr (+) 0 [10, 20, 30]"

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Find the biggest price with a fold

Command
docker exec haskell ghc -e "foldr max 0 [3, 9, 4]"

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Worked example: foldl and foldr with minus

CallHow it is worked outAnswer
foldl (-) 100 [10, 20](100 - 10) - 20, from the left70
foldr (-) 100 [10, 20]10 - (20 - 100), from the right90
foldl (+) 0 [10, 20](0 + 10) + 2030
foldr (+) 0 [10, 20]10 + (20 + 0)30

The cells students fill in are left blank in this preview.

Fold minus from the left

Command
docker exec haskell ghc -e "foldl (-) 100 [10, 20]"

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Fold minus from the right

Command
docker exec haskell ghc -e "foldr (-) 100 [10, 20]"

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Filter, then map, then fold

Command
docker exec haskell ghc -e "sum (map (* 2) (filter (> 500) [1000, 250, 700, 90]))"

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

A common mistake

Warning

Many people think foldl and foldr always give the same answer. They do for plus and times, where the order does not matter. They differ for minus, because 100 - 10 - 20 is not the same as 10 - (20 - 100).

About this lab and its source: Haskell lab: functional programming with functions and types, in the browser

Teaching a class? Set this module for your students with a teacher guide, marked assignments and a lab for every student.