In this article series, we tried to get into Elm as quickly as possible, by buiding three mini apps up to this point. In this article we’ll shift our focus on some more theoretical concepts, before we move onto the more advanced stuff. ## Working with List.map and List.filter

Elm works with immutable data structures. How do we then use the existing immutable data structure to find its members that satisfy only a certain condition or to produce different values based on existing values?

In other words, how do we filter a List? Or how do we even map over a List in Elm 0.19?

To achieve these two goals, we can use the `map` and `filter` functions. To keep things simple, we’ll look at the `List.map` and `List.filter` functions, although `.map` and `.filter` can also be used with some other data structures in Elm.

Let’s say our goal is to take a `List` of numbers and find only those that are divisible by 3. To begin, let’s define a function that will take an `Int` and return a `Boolean` (either `True` or `False`), based on whether the number given to the function is divisible by 3. Navigate to http://elmrepl.cuberoot.in, and type the following function definition:

``````findThrees num = modBy 3 num == 0
``````

The REPL will return:

``````<function> : Int -> Bool
``````

Our `findThrees` function takes an `Int` and returns a `Boolean`. Put differently, the expression `modBy 3 num == 0` is evaluated first. Let’s say that `num` is `3`, making the expression look like this: `modBy 3 3 == 0`. This expression is true, and thus the expression evaluates to the value of `True`, which is of type `Boolean`. Next, this value is assigned to the `findThrees` function.

In other words, if we call the `findThrees` function and give it number `3` as its parameter, the `findThrees` function will return the value of `True`, which is of type `Boolean`.

Next, let’s give our `findThrees` function to our `List.map`. The following code will not work. Try to guess why before reading the explanation:

``````List.map findThrees 3
``````

The answer is: the number `3` is an `Int`, not a `List`.

This is what REPL tells us too:

``````> findThrees num = modBy 3 num == 0
<function> : Int -> Bool
> List.map findThrees 3
-- TYPE MISMATCH ----------------------------------------------------------- elm

The 2nd argument to `map` is not what I expect:

5|   List.map findThrees 3
^
This argument is a number of type:

number

But `map` needs the 2nd argument to be:

List Int

Hint: I always figure out the argument types from left to right. If an argument
is acceptable, I assume it is “correct” and move on. So the problem may actually
be in one of the previous arguments!

Hint: Did you forget to add [] around it?
``````

Obviously, we can’t give just a `number` as the second argument of the `List.map` function. Instead, to make this work, we need to give it a `List` of `numbers`. Like this:

``````List.map findThrees [1,2]
``````

This time, success! REPL returns the following:

``````[False, False] : List Bool
``````

Let’s try giving it a List of three numbers:

``````List.map findThrees [1,2,3]
``````

This time, REPL returns:

``````[False,False,True] : List Bool
``````

Next, let’s type a List of 10 numbers, and store it in a variable:

``````ourList = [1,2,3,4,5,6,7,8,9,10]
``````

Running the preceding code in the REPL will return:

``````[1,2,3,4,5,6,7,8,9,10]
: List number
``````

Looking at the preceding code, we can say that a `List` of `numbers` is stored in a variable we called `ourList`. Now, let’s give the `findThrees` function to the `List.map` function, and pass the `ourList` as the second argument:

``````List.map findThrees ourList
``````

REPL returns a `List` of `Bool` values:

``````[False,False,True,False,False,True,False,False,True,False] : List Bool
``````

Finally, let’s try to replace `List.map` with `List.filter`:

``````List.filter findThrees ourList
``````

REPL returns a `List` of `Int` values:

``````[3,6,9] : List Int
``````

Now that we have practiced using `List.map` a little bit, let’s look at its anatomy. `List.map` takes two arguments, the first one being a function, and the second one being the actual `List`.

The function that is passed as the first argument to `List.map` is used to convert the second argument (the `List`) to a new `List`, based on the logic in the function. `List.map` does that by running the function we give it over each single member of the `List` provided. This behavior of `List.map` makes it a great candidate for improving our FizzBuzz app, which we built earlier in this article series.

For now, let’s run a `List.map` in our Elm-REPL. In order to be able to run `List.map`, we need to define a function it will use. So, let’s open Elm-REPL and define our custom `fizzBuzzer` function:

``````fizzBuzzer number = \
if modBy 15 number == 0 then \
"fizzBuzz" \
else if modBy 5 number == 0 then \
"fizz" \
else if modBy 3 number == 0 then \
"buzz" \
else \
Debug.toString number
``````

The backslash character - the `\` - is used to break onto the next line in Elm REPL.

Let’s now examine an improved FizzBuzz app, implemented with the help of `List.map`.

Here is the code:

``````module Main exposing (main)

import Browser
import Html exposing (text)

theList = [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]

fizzBuzz = "FizzBuzz"
fizz = "Fizz"
buzz = "Buzz"

fizzBuzzInput value =
if modBy 15 value == 0 then
fizzBuzz
else if modBy 5 value == 0 then
buzz
else if modBy 3 value == 0 then
fizz
else (String.fromInt value)

main =
text <|
Debug.toString <|
List.map fizzBuzzInput theList
``````

Note the `<|` operator. It simply means that we’ll start with `List.map`, then do `Debug.toString`, then do the `text` function.

We’ll continue our examination of `List.map` and `List.filter` in Elm by building a few more mini apps.

## List.map and List.filter are higher-order functions in Elm

`List.map` and `List.filter` are higher-order functions in Elm.

Higher-order functions are simply functions that operate on other functions.

Phrased differently, higher-order functions give superpowers.

To whom?

Of course, to regular functions! Which might just as easily be anonymous!

## A JavaScript Example Using `forEach`

An example in JavaScript to kick things off:

``````var moguls = ['Jeff Bezos', 'Elon Musk', 'Sergey Brin', 'Larry Page', 'Steve Jobs', 'Bill Gates'];
moguls.forEach(function(mogul,placeInArray){
console.log(placeInArray+1 + ". Mr. " + mogul);
});
``````

If you ran the above function in the console, you’d get:

1. Mr. Jeff Bezos
2. Mr. Elon Musk
3. Mr. Sergey Brin
4. Mr. Larry Page
5. Mr. Steve Jobs
6. Mr. Bill Gates

The function that’s being used as a parameter is the anonymous function:

``````function(mogul,placeInArray) {
console.log(placeInArray+1 + ". Mr. " + mogul);
});
``````

`forEach` is the higher-order function that’s operating on the above anonymous function.

We could have used the anonymous function on it’s own, like this:

``````var a = function(mogul, placeInArray) {
console.log(placeInArray+1 + ". Mr. " + mogul);
}
``````

Next, we’d have called it like this:

``````a("Nobody",0);
``````

Calling the `a` function like that would print this out to the console:

``````1. Mr. Nobody
``````

But, by passing the `a` function (in it’s anonymous variety) to the `forEach` function, we effectively give our a function super-powers! Now it can easily take on a full array of names, without too much effort on our side.

Alright, so let’s now see how to do that same thing in Elm.

## Mapping Over a List in Elm

What follows are three variations on the above JS code, simplified and re-written in Elm:

``````module Main exposing (main)
import Html exposing (Html)
moguls = ["Jeff Bezos", "Elon Musk", "Sergey Brin", "Larry Page", "Steve Jobs", "Bill Gates"]
addTitle name = String.append "Mr. " name
main : Html msg
main =
Html.text <| Debug.toString <| List.map (\x -> addTitle x) moguls
``````

Alternatively, we could have written it like this:

``````module Main exposing (main)
import Html exposing (Html)
moguls = ["Jeff Bezos", "Elon Musk", "Sergey Brin", "Larry Page", "Steve Jobs", "Bill Gates"]
"Mr. " ++ string
main : Html msg
main =
Html.text <| Debug.toString <| List.map addMrToAnyString moguls
``````

Yet another way to write this would be:

``````module Main exposing (main)
import Html exposing (Html)
moguls = ["Jeff Bezos", "Elon Musk", "Sergey Brin", "Larry Page", "Steve Jobs", "Bill Gates"]
main : Html msg
main =
Html.text <| Debug.toString <| List.map addMrToAnyString moguls
``````

In the above example, the `addMrToAnyString` is built using partial application of the append operator `++`.

This is possible because:

• all operators in Elm are functions
• all functions in Elm are curried, i.e. can be partially applied

The expression `(++) "Mr. "` is applying a single argument to the function `(++)` , thus producing a new function for the second argument.

## How List.map is used

Looking at the examples above, we always see this pattern:

``````List.map aFunction aList
``````

The `List.map` function takes two arguments, the first one being a function, and the second one being the actual list to be mapped over.

### Adding an Ordinal Number in Front of Each Member of the List

In this example, we’ll look at combining `List.map` with `List.indexedMap`.

Since `List.map` takes a function and a `List` and returns a `List`, it is entirely possible to then run `List.indexedMap` on the `List` that got returned:

``````module Main exposing (main)
import Html exposing (Html)
moguls : List String
moguls =
[ "Jeff Bezos", "Elon Musk", "Sergey Brin", "Larry Page", "Steve Jobs", "Bill Gates" ]
(++) "Mr. "
main : Html msg
main =
Html.text <|
Debug.toString <|
-- List.indexedMap (,) <|
List.indexedMap Tuple.pair <|
``````

The above code, when run, will produce a `List` of `2-tuples`, with the first member in each of the `2-tuples`, a `number`. Like this:

``````[(0,"Mr. Jeff Bezos"),(1,"Elon Musk"),...,(5,"Mr. Bill Gates")]
``````

Here is a slight improvement over the code above, that produces nicer results:

``````module Main exposing (main)
import Html exposing (..)
moguls : List { name : String }
moguls =
[ { name = "Jeff Bezos" }
, { name = "Elon Musk" }
, { name = "Sergey Brin" }
, { name = "Larry Page" }
, { name = "Steve Jobs" }
, { name = "Bill Gates" }
]
(++) "Mr. "
printMogul mogul =
li [] [ text (addMrToAnyString mogul.name)
]
mogulsFormatted =
div [] [ h1 [] [ text "Moguls" ]
, ol [] (List.map printMogul moguls)
]
main : Html msg
main =
mogulsFormatted
``````

And the output is:

``````Moguls
1. Mr. Jeff Bezos
2. Mr. Elon Musk
3. Mr. Sergey Brin
4. Mr. Larry Page
5. Mr. Steve Jobs
6. Mr. Bill Gates
``````

## Revisiting our FizzBuzz app

We can now use List.map to make a better FizzBuzz app:

``````module Main exposing (main)

import Browser
import Html exposing (Html, button, div, text)
import Html.Events exposing (onClick)

ourList = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]

fizzBuzzCheck fizz buzz fizzBuzz num =
if modBy 15 num == 0 then
Debug.toString fizzBuzz ++ ", "
else if  modBy 5 num == 0 then
Debug.toString buzz ++ ", "
else if  modBy 3 num == 0 then
Debug.toString fizz ++ ", "
else
(Debug.toString num) ++ ", "

main =
text (String.concat (List.map (fizzBuzzCheck "fizz" "buzz" "fizz buzz") ourList ) )
``````

The code of the above example can be found on Ellie app.

Before we start discussing what’s going on in the preceding code, let’s quickly update the main function using the forward function application operator, `|>`:

``````module Main exposing (main)

import HTML exposing (HTML, text)

ourList = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]

fizzBuzzCheck fizz buzz fizzBuzz num =
if num % 15 == 0 then
toString fizzBuzz ++ ", "
else if num % 5 == 0 then
toString buzz ++ ", "
else if num % 3 == 0 then
toString fizz ++ ", "
else
(toString num) ++ ", "

main =
List.map (fizzBuzzCheck "fizz" "buzz" "fizz buzz") ourList
|> String.concat
|> text
``````

Seeing the `main` function written in this different notation might make it simpler to understand what is happening in the preceding code. After importing the `Main` and `Html` modules, we declare the `ourList` variable and the `fizzBuzzCheck` function definition.

As we can see, the `fizzBuzzCheck` function takes four parameters and returns a value of type `String`.

The `main` function maps `ourList` based on the logic in the `fizzBuzzCheck` function, then we use the `String.concat` function to take that `List` of `Strings` that the `List.map` produced, and turn it into a single `String`, because the `text` function receives a single `String` value as its parameter.

This concludes our discussion of `List.map` and `List.filter` for now.

In the next article, we’ll look into currying and partial application, which will help us understand function signatures in Elm 0.19.