Javascript Functor, Applicative, Monads in pictures

Inspired by Swift Functors, Applicatives, and Monads in Pictures where the original article Functors, Applicatives, And Monads In Pictures is translated from Haskell into Swift, I would like to write a javascript version for it so that people not familiar with above languages can get the gist of essential functional programming concepts.
Some may feel this is a poor choice as it's against the common understanding that javascript is predominately imperative. However, according to our respectable javascript guru, Douglas Crockford in JavaScript:
The World’s Most Misunderstood Programming Language
. “… This is misleading because JavaScript has more in common with functional languages like Lisp or Scheme than with C or Java. …” I believe javascript is equipped with most of functional programming features and fully capable of writing functional code.

Here’s a simple value:


And we know how to apply a function to this value:

Simple enough. Lets extend this by saying that any value can be in a context. For now you can think of a context as a “box” that you can put a value in:

Now when you apply a function to this value, you’ll get different results depending on the containing box. This is the idea that Functors, Applicatives, Monads, Arrows etc are all based on.

In Haskell, Maybe type encapsulates an optional value which is either a value of type a (Just a) or empty (Nothing). It serves as a container referring to the “box” mentioned above where we can put stuff in. In javascript, there is no such thing like Maybe while we can easily see counterparts in other languages, such as Optional in Swift and Java 8, or Option in Scala.
Maybe is from Haskell to represent an optional value container with occupied and vacant state.

To wrap the value, let’s use Array in javascript to represent a containing box.

Functors

When a value is wrapped in a box, you can’t apply a normal function to it:

This is where map (fmap in Haskell) (<$> in Haskell) comes in. map is from the street, map is hip to containing box. map knows how to apply functions to values that are wrapped in a box. For example, suppose you want to apply a function that adds 3 to the wrapped 2 and assume there’s a map function exist:

Just what is a Functor, really?

A functor is any type that defines how map (fmap in Haskell) works.

And map magically applies this function because Array is a Functor. map was initially defined in ECMAScript 5. Now it’s widely supported in most of modern browsers and javascript runtimes. Before that, this is how map is implemented in Underscore.js :

Regardless it iterates each values, here’s what is happening behind the scenes when we write [2].map(plus3):

So then you’re like, alright map, please apply plusThree to a empty container.

It does end up with nothing. To illustrate it doesn’t apply a function at all, we tweak the function a bit:

Bill O’Reilly being totally ignorant about the functor

Like Morpheus in the Matrix, map knows just what to do; you start with None, and you end up with None! map is zen.

In javascript, Promise should be also considered a container that encapsulates eventual result of an asynchronous operation. It uses then function to interact with the yielded value based on its states:

In this case, Promise is also a functor. It has an interface where we can apply a function to its wrapped value.

Here’s another example: what happens when you apply a function to a list?

When an Array has multiple values, it naturally apples the function to each value and replace the array with new values.

Okay, okay, one last example: what happens when you apply a function to another function?

Here’s a function:

Here’s a function applied to another function:

The result is just another function!

In javascript, we can achieve that by doing function composition:

Applicatives

Applicatives take it to the next level. With an applicative, our values are wrapped in a container, just like Functors:

But our functions are wrapped in a container too!

Yeah. Let that sink in. Applicatives don’t kid around. Unlike Haskell, javascript doesn’t have a built-in way to deal with Applicative.

Says we have two wrapped values and we want to add them up:

What if we put a curried add function in map if the container is a functor ?

Now we have a wrapped curried function, how can we apply it to another wrapped value ? Assume ap (<*> in Haskell) is a function that can apply the function contents of a functor to an wrapped value.

If the we have multiple wrapped functions and values, we might expect this to happen:

Applicative pushes Functor aside. “Big boys can use functions with any number of arguments,” it says. “Armed with curry function, map (<$> in Haskell) and ap (<*> in Haskell), I can take any function that expects any number of unwrapped values. Then I pass it all wrapped values, and I get a wrapped value out! AHAHAHAHAH!”

Monads

How to learn about Monads:

  1. Get a PhD in computer science.
  2. Throw it away because you don’t need it for this section!

Monads add a new twist.

Functors apply a function to a wrapped value:

Applicatives apply a wrapped function to a wrapped value:

Monads apply a function that returns a wrapped value to a wrapped value.

Monads have a function flatMap (liftM in Haskell) (>>= in Haskell pronounced “bind”) to do this.

Suppose half is a function that only works on even numbers:

What if we feed it a wrapped value?

We need to use flatMap(>>= in Haskell) to shove our wrapped value into the function.

You can also chain these calls:

You might have the question that why don’t we just use map. I am glad you ask ! This is because half returns a wrapped value. If we use map, we are putting a container inside another container.

But why do we return a wrapped value in half ? In this case, we use the wrapped value to represent potential empty value and prevent the following calls in the chain from being executed if it’s empty. Let’s look at an other example:

Here’s a simple http request utility where we wrap the response in a promise:

With above utility, we try to make sequential calls to get the info of the first connection of contact 1.

The onFullfilled lambda can return either a value or a promise (thenable). When it returns a value, then is like a map function. When it returns another promise, then acts like a flatMap. The resolution state of returned promise will control the following operations and yield the eventual value (contact info of the first connection of contact 1.).

Conclusion

So, we can see the following traits:

  1. A functor is a type that implements map.
  2. An applicative is a type that implements ap.
  3. A monad is a type that implements flatMap.
  4. Array implements map, so it’s a functor.
  5. Promise implements map and flatMap through then, so it is a functor and a monad.

What is the difference between the three?

  • functors: you apply a function to a wrapped value.
  • applicatives: you apply a wrapped function to a wrapped value.
  • monads: you apply a function that returns a wrapped value, to a wrapped value.

So, dear friend (I think we are friends by this point), I think we both agree that monads are easy and a SMART IDEA(tm). Now that you’ve wet your whistle on this guide, why not pull a Mel Gibson and grab the whole bottle. Check out LYAH’s section on Monads. There’s a lot of things I’ve glossed over because Miran does a great job going in-depth with this stuff.

As a javascript programmer, you already more or less use functional programming in your daily work unconsciously !
Even though you might find it’s not too relevant as javascript is not strictly typed, I hope the article gives you a good introduction of functional programming and prepares you to learn other functional languages such as Scala.