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.↩︎