Intro #
The first topic we'll cover is the functor data type. Functors are everywhere whether you are aware of it or not.
Meet functor. #
The essence of a functor data type is that it is mappable. This simply means that it provides a container (or box) that we can map through in order to read or transform values. The focal point of that last sentence is - a container that we can map through.
Sounds kinda familiar, right? Letβs think for a second. In the context of JavaScript, can you think of any objects that fit this description?
const exampleFunctor = [1, 2, 3, 4, 5];
Above we see the myFunctor variable being set to an array, or a container, with values inside of it. Do you know what this means? It means you've been mastering functors all along π.
Prove it #
Hopefully, by now you're beginning to cozy up to the complex terminology used in FP.
The goal for this article (and every article I write focused on teaching concepts) is essentially the same: to remove the confusion that stems from FPs terminology.
JavaScript's Array [] type is a functor.
[Box of `a`s] ------> [Box of `b`s]
Testing map #
Below we see the the functor a which is a single element array [10]. Our second functor b is then created using JavaScript's built-in Array.prototype.map method.
const doubleIt = (x) => x * 2;
const functor = [10];
const x = functor.map(doubleIt);
const y = functor.map((x) => x * 2);
console.log(x.toString() === y.toString());

Functor Laws: #
There two functor laws are:
- Identity:
- id function must always
map a functor back to the same value, const id = x => x;[1,2,3].map(id); // returns [1,2,3]
- Composition:
- Given
g: x => y, f: y => z there must be a composition that directly X β Z.
This composition law was the same that I was forced to learn in algebra class. It' associative meaning that the order in which it is computer does not matter. Realizing this was a big "a-ha" moment when studying functional programming.
Ex.: (f β¦ g) β¦ h = f β¦ g β¦ h = f β¦ (g β¦ h)
Now that we know the functor laws lets apply them to another array. Below we have the following:
f takes an x and divides by .5g takes an x and multiplies by 16data is a functor containing 4 values.
const f = (x) => x / 0.5;
const g = (x) => x * 16;
const data = [25];
console.log(data.toString() === data.map((x) => x).toString());
console.log(
functor.map(g).map(f).toString() === functor.map((x) => f(g(x))).toString()
);
Maybe you're not impressed with our data array and the one value that it includes. functor's satisfy the Identity and composition law. Well, that's too bad but don't give up just yet.
We've seen functors in action and we've learned the rules that they must abide by. Now let's create one for ourselves.
The Box functor (often referred to as the Identity functor) will take a value as it's input. From there, it will return an object {} with a map method inside of it. When this map executes, it will apply it's input fn to the value inside and return it's result wrapped inside of. What's that you said? This map implementation sure sounds awfully familiar to JavaScript's``Array.prototype.map`. Well, friend, that's because it is !
Taking a look at the code snippet below we see how our Box function's map method is implemented.
πππ
Since you've made it this far, sharing this article on your favorite social media network would be highly appreciated π! For feedback, please ping me on Twitter.
Published