# Mapping

If you’ve used only one of Python’s iterator functions, there’s a good chance it’s this one. `map`

in Python

`map`

is essential because it’s the *functor* operation for lists: The notion of a functor is a small thing, but it provides a surprising depth of useful ideas to think about. We go into functors in depth in Functortown: A Map of the Territory. It operates over the *content* of the list but not the *structure* of the list. This implies, among other things, that the list that `map`

returns will always have the same number of elements as the input list.

`map`

This function has the same name in Haskell. `map`

in `Data.List`

and `Prelude`

You often see `map`

written in Haskell in its more polymorphic form, `fmap`

. `fmap`

in `Data.Functor`

and `Prelude`

This is a function that works on any type that has a `Functor`

instance. For lists, it specializes to `map`

. So this is the same as the previous example:

There is also an infix version of `fmap`

, called `(<$>)`

. So we could also write this example as:

Whether you use `fmap`

or `(<$>)`

is up to you – sometimes one or the other will be more convenient or clear in a particular context, but often it’s just a matter of personal preference.

## With more than one iterator

When `map`

is applied to a binary function and two list arguments, it does something a bit more: It steps through both lists in tandem, applying the function to one element from each of the lists.

This notion of iterating through two lists at once is sometimes called *zipping*. We will discuss zipping more when we get to the `zip`

function in the next lesson. Haskell calls this function `zipWith`

: `zipWith`

in `Data.List`

and `Prelude`

Python’s `map`

can be used with any number of arguments. Haskell does not overload like this, but has separate functions `zipWith3`

, `zipWith4`

, etc. to achieve the same result.

`starmap`

`starmap`

`itertools.starmap`

is like a cross between `map`

used with a single iterator and `map`

used with multiple iterators. It only takes a single iterator parameter, but the function being mapped doesn’t have to be unary. Each element of the iterator is a tuple containing as many arguments as the function has parameters.

In this example the function we mapped (`pow`

) has two parameters, and so each element of the iterator is a 2-tuple.

This is called “*star* map” because This use of `*`

in Python is called *iterable unpacking*. we could have also written it like this:

There’s no precise Haskell analogue here because Python generalizes over function arity in a way that Haskell doesn’t. If we wanted to compute exponents over a list of number pairs as the example above does, we’d probably write something like this:

For functions of two parameters, Python’s “star” is reminiscent of *uncurrying* in Haskell. `uncurry`

in `Data.Tuple`

and `Prelude`

If we wrote a function similar to `starmap`

, we might call it `uncurrymap`

:

For a function of two parameters, we can use this just like `starmap`

.

We mention `uncurry`

here mostly as a curiosity. It does not appear often in Haskell code, and the first version using `map`

and a lambda expression is the more common way to write this expression.