Functional JavaScript — Piping and Functors

John Au-Yeung - Jan 25 '21 - - Dev Community

Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62

Subscribe to my email list now at http://jauyeung.net/subscribe/

JavaScript is partly a functional language.

To learn JavaScript, we got to learn the functional parts of JavaScript.

In this article, we’ll look at how to pipe functions and functors with JavaScript.

Pipe

We can create a pipe function by creating a function that takes an array of functions as arguments.

It returns a function that takes a value and we call reduce on it with that calls fn with acc .

For example, we can write:

const compose = (...fns) =>
  (value) =>
  fns.reduceRight((acc, fn) => fn(acc), value)
Enter fullscreen mode Exit fullscreen mode

The only difference is that we used reduceRight instead of reduce so that we don’t have to call reverse to apply all the functions.

Composition is Associative

Composition is associative, this means we can rearrange the parentheses of our operations

For instance:

compose(f, compose(g, h)) == compose(compose(f, g), h)
Enter fullscreen mode Exit fullscreen mode

returns true .

Functors

Functor is a plain object that implements the function map while running River each value to produce a new object.

A functor is a container that holds some value in it.

For example, we can write:

const Container = function(val) {
  this.value = val;
}
Enter fullscreen mode Exit fullscreen mode

to create our container.

Then we can use new to invoke the Container constructor:

let foo = new Container(3);
Enter fullscreen mode Exit fullscreen mode

We can create a Container.of property to add a container to let us return a Container instance:

const Container = function(val) {
  this.value = val;
}

Container.of = function(value) {
  return new Container(value);
}
Enter fullscreen mode Exit fullscreen mode

We added the of static method to return a Container instance.

The of method just gives us an alternative to using the new operator to create the Container instance.

Then we can create a Container instance with the of method:

const nested = Container.of(Container.of(1));
Enter fullscreen mode Exit fullscreen mode

Then we’ll see the nested Container instances.

Functor Implements Method Called map

Functors implement the map method.

We can add it as an instance method by adding it to the prototype property:

const Container = function(val) {
  this.value = val;
}

Container.of = function(value) {
  return new Container(value);
}

Container.prototype.map = function(fn) {
  return Container.of(fn(this.value));
}
Enter fullscreen mode Exit fullscreen mode

Then we can use the map method after we create a Container instance.

For instance, we can use it by writing:

const squared = Container.of(3).map(a => a ** 2);
Enter fullscreen mode Exit fullscreen mode

Then squared is a Container instance with value being 9.

We call map repeatedly to repeat an operation.

So we can write:

const squared = Container.of(3)
  .map(square)
  .map(square)
  .map(square);
Enter fullscreen mode Exit fullscreen mode

Then squared is a Container instance with value being 6561.

Functor is just an object that implements a map method.

Conclusion

Functors are plain objects that have value.

The object has a map method.

We can pipe functions to call multiple functions and get the returned value.

Composition is associative, so we can rearrange the parentheses of our operations.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .