Functors in programming
Tags: functional, haskell, math, typescript
Published: 2022-02-19 22:07:10

In [category theory](https://en.wikipedia.org/wiki/Category_theory), functors are mappings between categories. I.e., functors are "containers" that lifts objects from one category to another. Here, I will present how to understand this concept in terms of types and functions.

## What is considered a functor?

To be considered **a functor**, a mapping between two categories **must preserve identity and composition**.

So let's imagine two categories _C_ and _D_ and a functor _F_ that maps objects from _C_ to _D_.

Identity is a unique morphism that connects one object to itself. This morphism is useful because if you compose this morphism with any other morphism _f_, you will still have _f_. I.e., these three functions (our morphisms) will behave in the same way:

```ts
(x) => f(id(x))
(x) => id(f(x))
(x) => f(x)
```

Preserve identity means that, for every object _x_ in _C_, mapping _F(x)_ with the identity morphism is the same as applying the identity morphism to _F(x)_. I.e., these two expressions must return the same thing:

```ts
F(x).map(id)
id(F(x))
```

And preserve composition means that mapping with a composition of functions in a functor will have the same behavior as mapping with the two functions separately. I.e., these two expressions must return the same thing:

```ts
F(x).map((x) => f(g(x)))
F(x).map(g).map(f)
```

## Types as objects and endofunctors

Knowing then what functors are, we can proceed to see how they can be applied in programming. In fact, the application is much simpler to understand than the theory. That's because in a programming environment, the type system will be considered our category, and all the functors will be just endofunctors.

And what is an endofunctor? It is basically a functor that maps objects from one category to the same category. In our case, all the functors will map values from one type (object) to another type (still in the same category).

![Functor](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z5rbasdx4o8u4w5jl8fz.png)
 

So let's see a simple example of the application of functors in TypeScript.

## The Maybe functor in TypeScript

As we saw, functor must be a mapping. So we have to define an interface that requires an implementation of a map function:

```ts
type FunctorMap<A, B> = (a: A) => B;

interface Functor<A> {
  map<B>(f: FunctorMap<A, B>): Functor<B>;
}
```

With this interface, it will be simple to implement the Maybe functor. In short, Maybe is a type that is able to contain an empty value (Nothing) or a value of a respective type (Just).

But to implement the map function, we have to ask ourselves: the Maybe type is a functor? To answer this, we just have to check if it respects the properties.

First, every value of type Maybe can be constructed two ways: _Maybe.nothing()_ or _Maybe.just(\<value\>)_. So,

```ts
// "Maybe" preserves identity
Maybe.just(x).map(id)
Maybe.just(x)
id(Maybe.just(x))

// And preservers composition
Maybe.just(x).map(g).map(f)
Maybe.just(x).map((x) => f(g(x)))
```

And what about the _Maybe.nothing()_ constructor? In this case, all maps will simply skip the application of the function, and return another _Maybe.nothing()_.

With this, we have demonstrated that the Maybe type is a functor. Let's finish to implement it now:

```ts
class Maybe<A> implements Functor<A> {
  constructor(private value: A | null) {}

  static just = <A>(value: A) => new Maybe<A>(value);
  static nothing = <A>() => new Maybe<A>(null);

  map<B>(f: FunctorMap<A, B>): Maybe<B> {
    if (this.value === null) return Maybe.nothing();
    return Maybe.just(f(this.value!));
  }
}
```

With this implementation, we can test how it will perform with a basic example:


```ts
Maybe.just<number>(1)
  .map((x) => x + 1)
  .map((x) => x * 2) // Just(4)

Maybe.nothing<number>
  .map((x) => x + 1)
  .map((x) => x * 2) // Nothing
```

## Conclusion

As you see, functors are very simple, especially if you see them as containers that implements a map function. If you look closely, this is very similar to what we do in JavaScript with arrays and promises, with just a bit more of formality :)