# A Short Introduction to Functors

--

This is the first post in a series on algebraic structures. The entire series may be viewed here.

Functors show up everywhere, and are an invaluable tool when doing functional programming. They’re really quite simple, and while they come from the math world, we can understand them enough to make use of them in our JavaScript code without any other mathematical or functional programming concepts. Functors are defined in terms of types, so this article uses Flow type annotations to make the types we’re dealing with explicit.

## Mapping over wrapped values

A functor is a data structure which acts like a container holding a generic type. There must be a `map` function defined for that data structure, which applies a function to the contents of that functor. For some generic class `Foo<A>` to be a functor, the signature of `map` must be:

`function map<A, B>(A => B, Foo<A>) : Foo<B>`

Many things can be functors. The Set type is a functor, and we can define a `map` function on it like this:

`function mapSet<A, B>(fn: A => B, s: Set<A>) : Set<B> {  const result = new Set();  for (let item of s) {    result.add(fn(item))  }  return result;}`

The Promise type is a functor, and its map function looks like this:

`function mapPromise<A, B>(fn: A => B, p: Promise<A>) : Promise<B> {  return p.then(fn);}`

While we introduced functors as containers holding a value, sometimes those containers can have interesting properties. For this reason, functors are often described as “values in a context.” For `Promise`, that context is that the value is in the future. `Set` may be seen as a plain container which holds a number of values, or it may be seen as a context in which a variable may hold one of a number of possible values. (In other words, you can look at a function which returns the set `{ 1, 2, 3 }` as something returning a container holding three results, or as something with one result, where that result might take on three possible values.) When we’re talking about values in context,`map` gives us a way to take functions written in a “normal” context and use them in the “special” context of a functor.

## A case when functors Maybe useful

`Maybe` is a commonly used functor in functional programming, whose context provides a practical benefit:

`type Maybe<A> = null | Just<A>;class Just<A> {  value: A;  constructor(value) {    this.value = value;  }}function mapMaybe<A, B>(fn: A => B, m: Maybe<A>) : Maybe<B> {  return m === null ? null : new Just(fn(m.value));}`

Like the previous functors, `Maybe` holds a value in context. The context of `Maybe` is that the value might be `null`. `mapMaybe` lets us work with a potentially null value in a safe way, by transforming the value with a given function if the value exists, and by just returning `null` without applying the function if the value is `null`.

This comes in handy when we want to apply functions to a value which might be `null`. We could modify our functions to check whether their input is null, but that would lead to boilerplate being sprinkled throughout our codebase. Instead, if we want to apply some function `foo` to some value `x` which might be null, we can perform this function application using `map`:

`foo(x); // might throw a null reference errormapMaybe(foo, x); // Will never throw`

This second approach has the benefit that Flow detects that `Maybe` is a union type, and will force us to handle the case when our result may be null. Plus, it allows us to differentiate the case where our input `x` is `null` and the entire computation is an error (and its result is `null`) from the case where the input `x` was a good value, but `foo` itself returned `null`. (In this case, our result will be `Just { value: null }`.

All sorts of other things can be functors. You’ve probably seen plenty in the course of day-to-day JavaScript: arrays, trees, streams, event emitters. If you have a type which takes one generic argument, there’s a good chance you can make it a functor, with one caveat: the functor’s `map` function must follow the functor laws.

## The functor laws

For something to be a functor, its `map` function has to obey two laws.

1. `map` must preserve identity. That is, for any functor `f`, `map(x => x, f)` has to be equal to `f`. This is called “identity” because the function which returns whatever value it was called with without changing it is often referred to as “the identity function”, or `id`. This function is implemented as `x => x`.
2. `map` must preserve function composition. For any functor `f`, and any functions `foo` and `bar`, `map(foo, map(bar, f))` must be equal to `map(contents => foo(bar(contents)), f)`.

In most cases, these laws are easy to obey as long as you’re keeping your functions pure. They are important because they let us reason about and compose functors in a consistent way, which lets us safely build abstractions on top of them. I recommend the exercise of looking at things which might be functors, and seeing whether and why these laws hold.

## Composing Functors

An important property of functors is that the composition of two functors is also a functor. That is, given a functor `Foo<A>` and a functor `Bar<A>`, we can define the type `type FooBar<A> = Foo<Bar<A>>`, and define the `mapFooBar` function as so:

`mapFooBar<A, B>(fn: A => B, a: FooBar<A>) : FooBar<B> {  return mapFoo(x => mapBar(fn, x), a);}`

As long as `mapFoo` and `mapBar` follow the functor laws, `mapFooBar` will as well.

So that’s it: when we’re writing JavaScript code, functors are things holding values which we can map over in a predictable way. It’s pretty common to use them without realizing they’re there, so being on the lookout for them can help us clarify and standardize the abstractions we create.

If you want to dig deeper into functors, I also wrote a post on applicative functors, a subtype of functors with much more advanced capabilities. My series on algebraic structures goes deeper into the practical uses of functors and applicative functors when writing functional code.

## Further Resources

Functors are one of many abstractions from the functional programming world which are defined as a generic data type following certain laws. Such abstractions are often called “algebraic structures”. The most common way to work with these structures in JavaScript is by using libraries which conform to the Fantasy Land specification, which details the interface which these structures should have. In Fantasy Land, functors are created by extending or wrapping data types such that the `map` function exists on the prototype of the type being used, like `array.map`, `promise.map`, `maybe.map`, etc. Alternatively, the Static Land specification defines a style like that used in this post, where functions are declared separately from the types they operate on. I prefer the static style, but the practical differences between the two are small, and the benefits that can be gained by using either are large.

If you want to use functors in typed JavaScript, flow-static-land provides a typed implementation of common algebraic structures in Flow, and ts-static-land provides an implementation in TypeScript. The funfix library does the same, and provides type declarations which enable it to be used from both Flow and TypeScript. Due to limitations in Flow and TypeScript’s type systems, more advanced techniques are needed to use these libraries. I’ve written about these techniques in my posts on higher-kinded types and brands.

The sample code from this post may be found here.

Thanks to Lizz Katsnelson for editing this post.

--

--

JavaScript developer with a focus on typed functional programming. He/him. https://jnkr.tech