We use cookies and other tracking technologies to improve your browsing experience on our site, analyze site traffic, and understand where our audience is coming from. To find out more, please read our privacy policy.

By choosing 'I Accept', you consent to our use of cookies and other tracking technologies.

We use cookies and other tracking technologies to improve your browsing experience on our site, analyze site traffic, and understand where our audience is coming from. To find out more, please read our privacy policy.

By choosing 'I Accept', you consent to our use of cookies and other tracking technologies. Less

We use cookies and other tracking technologies... More

# Login or registerto boost this post!

Show some love to the author of this blog by giving their post some rocket fuel ðŸš€.

# Login or register to start working on this issue!

Engineers who find a new job through Functional Works average a 15% increase in salary ðŸš€

# Maybe monad in JavaScript to save us from the hell of the null guard clauses

If one were asked to choose a single functional data structure from all the available ones, I bet they would choose the redoubtable Maybe, or Option under its other incarnation in Scala. This Maybe monad is in essence a simple box of computation that checks whether the data that it stores inside has or has no defined value and, based on this, either continues to apply further transformations to the value within or simply ignores them and safely routes the absence of value toward the finale of the computation chain.

#### Example 1

``````Maybe.of(undefined)
.map(value => value * 2)
.map(value => value * value)
.getOrElse(0) === 0
Maybe.of(2)
.map(value => value * 2)
.map(value => value * value)
.getOrElse(0) === 16
``````

will both print true. The last method `getOrElse(null)`, which simply unboxes the value or returns null if there is none. So we implement the null guard clause only once inside the `map` method without any need to have these null value checks scattered throughout all the callbacks passed to `map` in the above chain. Here is a short implementation.

#### Example 2

``````class Maybe {
constructor(value) {
this.__value = value;
}
static of(valueToBox){
return new Maybe(valueToBox);
}
getOrElse(elseVal) {
return this.isNothing() ? elseVal : this.__value;
}
isNothing() {
return this.__value === null || this.__value === undefined;
}
map(fn) {
return this.isNothing()?
Maybe.of(null):
Maybe.of(fn(this.__value));
}
}
``````

We have now contained all our null checking logic in one place, reducing the number of possible errors in the future.

##### Tip.
Youâ€™ll soon see a lot of `getOrElse(null)` and `getOrElse([])` calls in your code. They can be optimized into:

``````...
getOrNull() {
return this.getOrElse(null);
}
...
``````

and

``````...
getOrEmptyArray() {
return this.getOrElse([]);
}
...
``````

There is one caveat, though. What if somewhere in the map chain we have a callback that returns another Maybe?

#### Example 3

``````const mbMapper = x => Maybe.of(x).map(_x => _x * 2);
//-> returns a Maybe
Maybe.of(2).map(mbMapper).getOrElse(0) === ?
``````

Our result is `Maybe(4)` Weâ€™d apparently need a second call to` getOrElse()` method to retrieve the value. Such constructions would soon pollute our code. Moreover it would effectively prevent our `Maybe` type from being a monad in the mathematical sense of the term. As a monad must flatten the monad hierarchy flowing through its chain. To tackle this problem weâ€™ll introduce a new method: `flatMap`.

#### Example 4

``````...
flatMap(fn){
if(this.isNothing()) return Maybe.Nothing();
const m = fn(this.__value);

return m.isNothing() ?
Maybe.Nothing() :
Maybe.of(m.__value);
}
...
``````

Now we can do

``````const mbMapper = x => Maybe.of(x).map(_x => _x * 2);
Maybe.of(2).flatMap(mbMapper).getOrElse(0) === 4 // prints true
``````

So the whole implementation of our Maybe monad looks now like:

#### Example 5

``````class Maybe {
constructor(value) {
this.__value = value;
}
static of(valueToBox){
return new Maybe(valueToBox);
}
flatMap(fn){
if(this.isNothing()) return Maybe.Nothing();
const m = fn(this.__value);

return m.isNothing() ?
Maybe.Nothing() :
Maybe.of(m.__value);
}
getOrElse(elseVal) {
return this.isNothing() ? elseVal : this.__value;
}
getOrEmptyArray() {
return this.getOrElse([]);
}
getOrNull() {
return this.getOrElse(null);
}
isNothing() {
return this.__value === null || this.__value === undefined;
}
map(fn) {
return this.isNothing()?
Maybe.of(null):
Maybe.of(fn(this.__value));
}
}
``````

All that is left now is to ensure that we are indeed dealing with a monad here. To be considered as such our Maybe structure needs to satisfy the following laws (using chai testing library syntax):

1. Left identity:
``````it("left identity law should be satisfied", () => {
const value = 2;
const mbValue = Maybe.of(value);
const mapper = x => Maybe.of(x * 2);
expect(mbValue.flatMap(mapper)).to.deep.equal(mapper(value));
});
``````
2. Right identity:
``````it("right identity law should be satisfied", () => {
const mbValue = Maybe.of(2);
const mapper = x => Maybe.of(x);
expect(mbValue.flatMap(mapper)).to.deep.equal(mbValue);
});
``````
3. Associativity:
``````it("associativity law should be satisfied", () => {
const f = val => Maybe.of(val + 1);
const g = val => Maybe.of(val * 2);
const m = Maybe.of(1);
const lhs = m.flatMap(f).flatMap(g);
const rhs = m.flatMap(x => f(x).flatMap(g));
expect(lhs).to.deep.equal(rhs);
});
``````
The above tests prove that our Maybe is none other than a monad.
If you're passionate about Front End development, check out our JavaScript job-board here!

Originally published on medium.com