# Notes on Functional Programming III: Functor, Applicative & Monad

Preliminary: The Fantasy Land algebra is a specification which many good functional libraries implement and covers additional laws of algebraic structures which I won’t cover.

## Functor

A **functor** is just a container for values with a `map`

method that applies a function to the values while consistently returning the new values in the same container.

According to this definition an array is a functor:

```
const xs = [1, 2, 3];
// Array.isArray(xs) === true
const ys = xs.map(x => x);
// Array.isArray(ys) === true
```

You have an array with values, apply a function via `map`

to each of the values and get an array with values back.

Unfortunately, not all data structures have a map function so you might need to write a wrapper which could be as simple as:

```
class Wrapper {
constructor (value) {
this.value = value;
}
map(f) {
return new Wrapper(f(this.value));
}
}
```

### Advantages of a functor

**A functor enables generalized behavior**

It allows you to map over values without being tied to a specific structure.

Furthermore, all advantages of `map`

over `for`

loops apply to which is mainly compactness and expressiveness.

## Applicative

An **applicative** is an extension of a functor and is used to be able to apply functors to each other. In order to do this, it wraps a function around the value which is wrapped by the functor. The required `ap`

method is used to automatically apply the already partially applied and wrapped function via `map`

to the wrapped value of another functor:

```
Wrapper.prototype.ap = function (wrapped) {
return wrapped.map(this.value);
};
```

Additionally, an applicative must provide an `of`

method which is used to create an instance with default minimal context:

```
Wrapper.of = x => new Wrapper(x);
```

Functors which only have an

`ap`

method are called Apply. Functors which only have an`of`

method are called Pointed Functors. If they have both they are called Applicatives.

We will use `of`

to write a new `map`

method:

```
Wrapper.prototype.map = function (f) {
return Wrapper.of(f(this.value);
};
```

Let’s assume we have the following setup:

```
const add = x => y => x + y;
const wrapperOne = Wrapper.of(1);
const wrapperTwo = Wrapper.of(2);
const wrapperOneAdd = wrapperOne.map(add);
```

where `add`

is a curried function and `wrapperOneAdd`

is an object of type `Wrapper`

with the wrapped value of `y => 1 + y`

.

To be explicit: The first box contains the integer `1`

. The second box the result, i.e. `y => 1 + y`

, of the function `add`

which was applied to the boxed `1`

. So we are two levels deep now.

Using the `ap`

method would result in a new wrapped value:

```
wrapperOneAdd.ap(wrapperTwo);
// Wrapper {value: 3}
```

The wrapped partial function `y => 1 + x`

is applied to the unwrapped value of `2`

, i.e. `y => 1 + 2`

which is then returned as a wrapped value `3`

.

Keep in mind the box is always of the same type, the values not necessarily.

### Advantages of an Applicative

An applicative is best used if you have several tasks which don’t depend on each other, e.g. if you have several independent calls you could write the following interface:

```
Task.of(renderPage)
.ap(Http.get('orders'))
.ap(Http.get('billing'));
.ap(Http.get('ads'));
.ap(Http.get('tracking'));
```

**An applicative promotes simplicity**

Generally speaking it creates a simple interface for complex code. However the real advantages can only be grasped if a specific applicative is used. General applicatives like the one described above are rather rare. Further information will be provided in the monad section.

## Monads

A **monad** applies a function which returns a wrapped value to a wrapped value. The main advantage over applicatives is that they run sequentially by providing the `chain`

method. Here is an implementation of a general monad:

```
class Monad {
static of(value) {
return new Monad(value);
}
constructor (value) {
this.value = value;
}
map(f) {
return Monad.of(f(this.value));
}
ap(monad) {
return monad.map(this.value);
};
chain(f) {
return this.map(f).value;
}
}
```

Normally you would also implement the `join`

method which is a straight forward helper method to return the value which helps us to flatten monads when chained:

```
join() {
return this.value;
}
chain(f) {
return this.map(f).join();
}
```

However, just like general applicatives, a general implementation of a monad doesn’t make much sense. One of the most common practical examples of a specific monad is the **Maybe monad**:

```
class Maybe extends Monad {
static of(value) {
return new Maybe(value);
}
constructor(value) {
super(value);
}
isNothing() {
return (this.value === null || this.value === undefined);
}
map(f) {
return this.isNothing() ? Maybe.of(null) : Maybe.of(f(this.value));
}
}
```

It just checks whether the wrapped value is `null`

or `undefined`

and if it is, returns a wrapped `null`

. Why is this interesting? Well, first of all it avoids pesky null checks. Additionally, it provides safety from runtime errors when chaining several methods where one may fail to return a value:

```
const prop = p => o => o[p];
const getUsername = account => Maybe
.of(account)
.map(prop('personal'))
.map(prop('user'))
.map(prop('name'));
// Might be retrieved async!
const user = {
personal: {
user: {
name: 'John Doe'
}
}
}
getUsername(user);
// Maybe { value: 'John Doe' }
```

If one property in the path wouldn’t exist, we wouldn’t get an error but a `Maybe`

with value `null`

.

Right now you probably think you have a déjà vu and yes you are correct *Promise* is a monad.

### Advantages of a monad

In general monads are concise and expressive with the ability to encapsulate side-effects.

The advantages of specific monads are as numerous as their implementations ranging from the simple forms of *State* ensuring the correct state flow, *Sequence* where `;`

can be a monad for control flow, *Maybe* handling null checks, *Promise* handling asynchronicity up to the complex ones of *Probability Distribution* or *Transaction* for databases.

## Comments

No comments yet.