# Implementing JavaScript Functors and Monads

# Introduction

This concepts are very used nowadays on functional programing, but because of the heavy mathematical background, sometimes it may be confusing to understand all the definitions.

In this post I’ll try to clear a little more the understatement of this subject, but not going too deep and using simple examples, helping you to create your own f*unctors *and *monads*. I wish you enjoy it!

# Functors

## Definition

Following the mathematical definition, and relating in the programing world in a very simple way, *functors* are a *mapping *using a function *f(x) (*or composite function *f(g(x))* for instance) on a *category A* generating a *category B, *creating a new *image, *respecting the *morphism*. In other words, is any object we can *map* and apply a function generating another object instance of the same type and connections.

Let’s check an example:

`[1, 2, 3].map(val => val * 2); //generates [2, 4, 6]`

So, we can see that **Array** is a functor, because it respects the same type (results in other Array instance) and the connections too (have the same number of items).

## Creating a Functor

With this in mind, let’s create a functor. I’ll take my previous post example of the *Train* class: (you may think I really like trains, right?)

The map method will return a image (**another** train, with the same number of **connections**) with the wagons content:

`["gold", "gold", "people"]`

But, if I try to do this:

Now we have a problem, because we need to reimplement the *map *method for all the children classes, as the *Train* map just return a **new Train**, causing it to break the rule of the *morphism*. How can I do to make the children classes return themselves instances without the need of overwriting the parent method?

## Reflection using Symbol.species

Note: if you don’t know about Symbols, you can check my previous post, where I explain a little about it behaviour and what are the “well-known symbols” , which I focus about another one, the

Symbol.iterator.

So, as the title says, we’re going to use the well-known symbol **species** for *reflection, *to make our current class create a new instance of **itself** while returning the *map* call:

This way, any child class instance that uses the *Train.map* are going to be a f*unctor* too, as they’re going to respect the *morphism*.

# Monads

## Definition

Monads are more complicated to explain, but I’ll try to make a parallel on what we know, and using a description given by Eric Elliott:

Functions map:

`a => b`

which lets you compose functions of type`a => b`

Functors map with context:

`Functor(a) => Functor(b)`

, which lets you compose functions`F(a) => F(b)`

Flatten and map with context:

`Monad(Monad(a)) => Monad(b)`

, which lets you compose lifting functions`a => F(b)`

So, the monad basically is a *functor* but with the special power to unwrap any value from its context using the flatMap. Arrays **are** *monads *as you can flat then:

`[ "H", ["e"], ["l"], ["l"], "o"].flat();`

// returns ["H", "e", "l", "l", "o"]

And flatMap then:

`[1, [2], 3].flatMap(val => val * 2)`

// returns [2, 4, 6]

You can see that if it’s a primitive value, the flat map just applies the context (array) to it, but when it finds a wrapped value, it lifts its context to the same level of the *flatMap* caller.

## Creating a Monad

I’m going to use an example from my childhood, coming from the super sentai series, the **Zords**.

In this series, a Zord is a giant robot where the pilots were able to join multiple ones to create a MegaZord, which is basically **another Zord**.

For instance, the **Megazord **is the composition of all the rangers Zords, and the **Mega Dragonzord** is the composition of the Megazord + the green ranger’s Zord.

In our code, we want basically to accomplish something like this:

As a *monad* we’re going to be able to “extract” this values from the context using the flatMap, lifting one layer of *Zords*. So, the implementation should be:

With that, we can check the following behaviour:

Zord.of('white')

.flatMap(rng => console.log(rng)); // logswhiteZord.of(Zord.of('white'))

.flatMap(rng => console.log(rng)); // logswhitetoo// Flat mapping also make it return the inner wrapped Value

// Zord(Zord('white')).flatMap() -> Zord('white')

Nice, we accomplished what we wanted. Maybe you probably saw this same behaviour before, in *Promises*:

Promise.resolve("hello")

.then(res => console.log(res)); // logshelloPromise.resolve(Promise.resolve("hello"))

.then(res => console.log(res)); // logshellotoo

“So, the promises are monads and the resolution method

then( )is aflatMap!”

**Yes, you’re right!** Promises encapsulate asynchronous values, which can produce (or not) values when flattened. That’s why you can return a value or promise inside the *then( )* callback, which always lifts the values (when needed), unwrapping from any *Promise *context. And also, you can keep chaining calls of the Zord’s *flatMap( ) *or the Promise’s *then( )*, as they always return their respective wrappers.

Note: The Promises then( ) method acts as a magical unwrapper, lifting how many contexts possible to reach the wrapped value (basically a

deepFlatMap). So differently from a common monad :“Promise.resolve(Promise.resolve(Promise.resolve(‘hello’))).then(func)”

‘func’ will actually get the ‘hello’ value instead of the Promise<’hello’>.

So, going back to the *Zords *(Zordon is calling us!), if we look into the code, any class extending *Zord* isn’t going to respect the *morphism, *as we call from the static *of( ) *method a “*new** *** Zord( )**” directly.

We need to use the same thing we’ve used before, the *Symbol.species, *and through reflexion, get the right constructor:

And now we can create a (not so boring) class child of *Zord*, while still being a *monad* and* *respecting the *morphism:*

You can see the result below:

# Conclusion

After understanding a little more about *functors* and *monads*, you figure out that’s **all about function composition **and how to work in different contexts with it.

Well, that’s all! If you liked it, give it some claps 👏 and show your support. Critics and suggestions are always welcome, so don’t be afraid and use the comment section 👇, give your feedback 😃.

# Resources

# Special Thanks to

Yannick Spark for pointing me out corrections on the definition of the monad behaviour.