Javascript Functor, Applicative, Monads in pictures

Tze-Hsiang Lin
Jul 10, 2016 · 8 min read

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:

Image for post
Image for post

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:

Image for post
Image for post

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.

Image for post
Image for post
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:

Image for post
Image for post

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:

Image for post
Image for post

Just what is a Functor, really?

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

Image for post
Image for post

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):

Image for post
Image for post

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

Image for post
Image for post

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

Image for post
Image for post
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?

Image for post
Image for post

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

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

Here’s a function:

Image for post
Image for post

Here’s a function applied to another function:

Image for post
Image for post

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:

Image for post
Image for post

But our functions are wrapped in a container too!

Image for post
Image for post

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.

Image for post
Image for post

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

Image for post
Image for post

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:

Image for post
Image for post

Applicatives apply a wrapped function to a wrapped value:

Image for post
Image for post

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:

Image for post
Image for post

What if we feed it a wrapped value?

Image for post
Image for post

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

Image for post
Image for post

You can also chain these calls:

Image for post
Image for post

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.

Image for post
Image for post

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?

Image for post
Image for post
  • 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.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch

Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore

Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store