# Functors in Haskell

In this post I'll write about functors only in programming terms, specifically in Haskell.

In the last post we discussed the $Maybe$ functor. A functor is not itself a type, it's a type constructor as given by the definition of the typeclass in Haskell:

The $Functor$ typeclass requires an implemention of $fmap$ for every instance of that typeclass. $fmap$ is a higher order function which takes a function $a \rightarrow b$ and "lifts" it into a function that acts on the function $f a \rightarrow f b$ which itself is a mapping from functor-to-functor.

This means really that we can take any ordinary function and apply it to a functor, which then will return a functor.

**List is a functor**

A list in Haskell is a coproduct type defined recursively as:

The built-in list type has a functor instance. Here's the implementation:

We simply apply the function to the head of the list, then $fmap$ that function over the tail of the list and combine them.

**The Reader functor**

This is something that is, on the surface, quite different to the functor examples shown before ($Maybe$ and $List$).

In Haskell functions are types. A partially applied function is also a type in Haskell - here we take a function $a \rightarrow b$ and partially apply it $(\rightarrow) a$ - it's a function that's awaiting a second type argument $b$, this is also a type constructor. When it receives it's second type it becomes a full type - a total function.

This type constructor (partially applied function) defines a whole family of type constructors parameterized by the type $a$. Here, in the context of the $Reader$ functor we want to take a type $a$ and map it into a type $r \rightarrow a$. In order to show that $Reader$ is a functor we want to lift the original function $a \rightarrow b$ into $(r \rightarrow a) \rightarrow (r \rightarrow b)$. In Haskell:

That is, we apply $g$ and then $f$ - it's the only way to make the two arguments typecheck. In pointfree form:

In simple terms it's a thing that takes a resource $r$, ($r \rightarrow a$) to which we apply a regular function $a \rightarrow b$. Here's an example:

In other words we have $f$ as a partially applied function $(* 3)$ which is awaiting it's argument - we have a resource $r$ to which we pass as the first argument to the partially applied function $g$ $(+100)$, the result of this $(r + 100)$ gets passed to $f$ which is $((r + 100) * 3)$ - so the result is 303 given $r = 1$ as above. Remember we are dealing with partially applied functions, so the whole process kicks off when we are given an $r$. This is applied to the second function $(+ 100)$ and the result of that $(101)$ is passed to the first function.

There is a lot more to the $Reader$ functor - it's actually a $Monad$ which itself "derives" from $Functor$. This is just some of the detail in the context of functors.

# Functor composition

This follows from the rules of category. Given the following function:

We have a function that takes a functor $[a]$ to another functor $Maybe [a]$ which is itself a functor containing a functor. In order to apply some function $f$ to this we need to $fmap$ into the outer $Maybe$ functor, and then $fmap$ again to break into the inner $[]$ functor. A simple example on a list of integers that may or may not have a tail:

**Gaining intution**

Functors can be thought of as a **context** in which some value(s) is/are stored. For example the $Maybe$ functor is a context that may or may not contain a value. $IO$ is a context that contains those values that come from I/O and are thus unpredictable, and so on.

This doesn't always make the most sense as functors like the list functor are better thought of as a **container**. There are other functors like the constant functor that don't map well to this context worldview, and so are better thought of as a thing that contains something, but we don't really care about what it contains. We only care about preservation of the structure of the categories upon which the functors act on.

In a nutshell the functor typeclass allows us to apply pure functions to values that are in a context/container - this means we are separate our program logic neatly into pure and effectful parts.