This is a tutorial on functors. It is inspired by the already-excellently written article here.

# What is a Functor?

In Haskell, there is a **Functor** type class. If a type is an instance of
the **Functor** class, it is essentially a container type that adds
*context* to any value.

The **Functor** class is defined as follows:

. That looks a bit weird, so I will rewrite it:

. So, for a container type to be a real **Functor**, it has to be able to
take in a function, and be able to modify the value contained inside
itself *without changing the context*. This is *extremely useful*. Let’s
look at some functors.

## The List Functor

Imagine you have a list with some numbers in it: `xs = [1, 2, 3]`

. Also
imagine you already wrote this function below:

. Now, you’d like to use `makeStatement`

on the list `xs`

, which has a
type `[Int]`

, so that every `Int`

inside the list gets transformed
according to `makeStatement`

. Thankfully, **List** already has an instance
of the **Functor** class, so we can do it like this:

. Though, since **List** defines `fmap`

with a shorter-named `map`

, we can
just use `map`

instead of `fmap`

to save ourselves a keystroke.^{1}
While we’re at it, we might as well drop the `xs`

because it’s
redundant.

This is immensely useful. Without the **Functor** class, you’d have to use
pattern matching to manually extract the values contained in the list
first before applying functions on them. Imagine a sophisticated,
recursive binary tree with millions of elements — as long as the
container type has an instance for **Functor**, you can just use a
one-liner `fmap`

to universally apply the function at hand to every
single element inside the tree (and rest assured that the *context* for
all the individual values and their interrelationships remain untouched
— a win win!).

For empty lists, You can still pass along a function with `fmap`

into
them, but nothing will happen because they are empty (that is, there are
no values inside to modify with the function).

## The Maybe Functor

Let’s look at the **Maybe** type just to prove that they are also
functors.

**Maybe** is a container, except that it can only contain just 1 element
(unlike **List** which can hold multiple elements). **Maybe** has two
constructors: `Just`

and `Nothing`

; you can use `Just`

to put a value
into the **Maybe** type, like how you can use the `(:[])`

function to put
a single item into a list. Alternatively, you can use `Nothing`

to
denote the empty **Maybe** container (like `[]`

for lists).

Again, using `fmap`

on an empty container will return the empty
container as-is:

## The Tuple Functor?

You might be wondering — what about tuples? Well, because tuples hold
*different* types in a single container, it is impossible to implement
`fmap`

for it. Recall the type signature required for `fmap`

:

. Notice that the container must contain a single type `apples`

—
tuples by their nature have arbitrary numbers of *different* types (they
have apples *and* oranges in them already). This is the reason why we
don’t (and can’t) have an `fmap`

function for tuples.

# Conclusion

Functors are awesome. If you ever define your own custom container type,
be sure to make an instance for **Functor** to make life easy for
everyone.

I imagine other types’

`fmap`

implementation will have longer names, which would encourage you to just use the universal, 4-letter`fmap`

function instead.↩︎