Transforming Lists with map

Introduction: A New Way to Transform Lists

Welcome to the second unit of our course! In programming, you will often encounter situations where you need to apply the same change to an entire collection of items. Consider real-world tasks like doubling all quantities in a recipe or capitalizing a list of names.

In our previous course, you learned to handle this by manually defining the process: you would change the first item (the "head" of the list) and then repeat the process for the remaining items (the "tail"). While this works, it requires a lot of repetitive code.

To solve this, Haskell provides a built-in higher-order function called map. The map function handles the heavy lifting for you. It automatically traverses your list, applies a rule to every single item, and returns a new list of results. This allows us to write much cleaner and more readable code.

Here is the type signature for map:

Haskell
map :: (a -> b) -> [a] -> [b]

This tells us that map takes a function from a to b, then a list of a values, and produces a list of b values. The input and output element types can be the same, but they do not have to be. The result list's element type follows whatever the function returns.

Quick Recall: Strings as Lists and Partial Application

Before we begin using map, let's briefly recall two important concepts from our previous lessons that will make our work much easier today.

First, remember that a String in Haskell is simply a list of characters, written as [Char]. This means any tool we use to work with lists can also be used to work with text.

Second, in our very first unit, we learned about partial application. When we write an expression like (+ 1), we are creating a function that is waiting for one more number. Once it receives that number, it will add one to it. We can use these partially applied functions directly to save time. We can also create comparison functions in the same style, such as (> 20), which checks whether a number is greater than 20.

Step 1: Using map with Named Functions

Let's look at how map works by using a standard, named helper function. Imagine we have a list of numbers and we want to double every number in that list.

First, we define a simple function that doubles a single integer.

Haskell
double :: Int -> Int
double n = n * 2

Now, instead of manually writing a step-by-step process to apply this to a list, we can use map. The map function expects two arguments: the function you want to apply and the list you want to change.

Haskell
double :: Int -> Int
double n = n * 2

doubled :: [Int]
doubled = map double [1, 2, 3, 4]

Because double turns an Int into an Int, our doubled list is a list of integers ([Int]).

Let's print this in our main block to see it in action.

Haskell
double :: Int -> Int
double n = n * 2

doubled :: [Int]
doubled = map double [1, 2, 3, 4]

main :: IO ()
main = do
  print doubled

Output:

text
[2,4,6,8]

Every number in the list was successfully doubled, and we did not have to write a single line of repetitive code!

Sign up

Join the 1M+ learners on CodeSignal

Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal