Promise as Functor (Video)

Idea: The Promise then can be seen as a map method that applies a function to the expected value.

Async Id Functor

this is more of an idea i came up in order to make more obvious that a Promise is just an asynchronous identity functor ( or an async Either functor if you include an error callback) .

We already talk about how the Id entity functor is the minimal functor in a js world

const Id = (v) => ({
value: v,
map: (f) => Id(f(v))
});

It doesn’t matter if we don’t have the value yet since we can instead of the v leave a subscription callback that will eventually have the value so we can

const Id= (executor) => ({
map: (f) =>…
});

Which we will use in this way when we have a value

Id(r => r(5))

Now in order to create the map we still follow the same steps that we follow to create a map for a Functor

  1. Open the container and access the value v. We can access the value by adding a subscription to the callback like this executor(v=>…) now we have the value (whenever this value becomes available, we do not care .What matters to us is that we have a variable v to treat as a value)
  2. Apply the function f executor(v=>f(v))
  3. We must repackage this into something that is the same as the initial packageId = (executor) => ({…}) Fortunately for us this form of Id expects a callback and not a value, so we have to pass on the constructor something that looks like this map: (f) => Id(resolve => … )this means that we can pass the value f(v) from executor (v=>f(v)) into the r and in this way we have completed the construction

What we get is the following:

var Id = (executor) => ({
map: f => Id(resolve => executor(v => resolve(f(v)))),
matchWith: pattern => executor(v => pattern(v))
})

Id(resolve => resolve(5)).map(x => x + 4).matchWith(console.log)

Run This: Js Fiddle

Promise as Functor

We will start by extending the Custom Promise seen previously to a functor, by providing a map method that obeys the functor laws and thus promote native Promise into a functor.

The Native implementation of promises (based on the Promises/A+ specification ) has a map achieved by overloading the then:

var thenableMapResult = new Promise((resolve,reject)=>resolve(5))
.then(x=>x+3)
.then(console.log)//8

Run This: Js Fiddle

This Section is clearly to just provide some understanding on the mechanics behind the .then as a map .

We have said that the usual metaphor for a functor is “a container.” A Promise can be seen as a container that takes a value and wraps it, until it is resolved. In order to promote Promise to Functor, there must be a mapping function that would be able to lift any function and give a new Promise with the lifted value.

Here is one possible mapping function that preserves structure:

Promise.prototype.map = function(f) {  
var initialPromise = this;
return new Promise(function(resolve,reject) {
initialPromise.then(result => resolve(f(result)))
.catch(reject);
});
}

Run This: Js Fiddle

The mapping function that lifts the function f: a→b follows the steps:

  1. Waits for the result of the Promise (so in a way unwraps the contained value) initialPromise.then( )
  2. Applying the function f : result => resolve(f(result))
  3. wraps the resulting value again into a new Promise : return new Promise() because when we implement a map, we always return something of the same type in order to belong to the same category (in this case type) or Promise.

Something worth pointing out here is the .catch(reject) this part belongs to the path of failure and ignores the f mapping. We are going to come back to this observation many times throughout this book.

Get the full functional JavaScript bundle

--

--

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