Imagine that we want to apply a series of functions to `x`

if and only if `x`

is non-null:

```
if (x !== null) x = a(x);
if (x !== null) x = b(x);
if (x !== null) x = c(x);
```

Now let's say that we need to do the same to `y`

:

```
if (y !== null) y = a(y);
if (y !== null) y = b(y);
if (y !== null) y = c(y);
```

And the same to `z`

:

```
if (z !== null) z = a(z);
if (z !== null) z = b(z);
if (z !== null) z = c(z);
```

As you can see without a proper abstraction, we'll end up duplicating code over and over again. Such an abstraction already exists: the *Maybe* monad.

The *Maybe* monad holds both a value and a computational context:

- The monad keeps the value safe and applies functions to it.
- The computational context is a null check before applying a function.

A naive implementation would look like this:

*?? This implementation is for illustration purpose only! This is not how it should be done and is wrong at many levels. However this should give you a better idea of what I am talking about.*

As you can see nothing can break:

- We apply a series of functions to our value
- If at any point, the value becomes null (or undefined) we just don't apply any function anymore.

```
const abc = obj =>
Maybe
.of(obj)
.map(o => o.a)
.map(o => o.b)
.map(o => o.c)
.value;
const values = [
{},
{a: {}},
{a: {b: {}}},
{a: {b: {c: 42}}}
];
console.log(
values.map(abc)
);
```

```
<script>
function Maybe(x) {
this.value = x; //-> container for our value
}
Maybe.of = x => new Maybe(x);
Maybe.prototype.map = function (fn) {
if (this.value == null) { //-> computational context
return this;
}
return Maybe.of(fn(this.value));
};
</script>
```

**Appendix 1**

I cannot explain what monads are as this is not the purpose of this post and there are people out there better at this than I am. However as Eric Elliot said in hist blog post JavaScript Monads Made Simple:

Regardless of your skill level or understanding of category theory, using monads makes your code easier to work with. Failing to take advantage of monads may make your code harder to work with (e.g., callback hell, nested conditional branches, more verbosity).

**Appendix 2**

Here's how I'd solve your issue using the *Maybe* monad from monetjs

```
const prop = key => obj => Maybe.fromNull(obj[key]);
const abc = obj =>
Maybe
.fromNull(obj)
.flatMap(prop('a'))
.flatMap(prop('b'))
.flatMap(prop('c'))
.orSome('????')
const values = [
{},
{a: {}},
{a: {b: {}}},
{a: {b: {c: 42}}}
];
console.log(
values.map(abc)
);
```

```
<script src="https://www.unpkg.com/[email protected]/dist/monet.js"></script>
<script>const {Maybe} = Monet;</script>
```

0
Created by customcommander on 2020-03-11 09:11:54 +0000 UTC

Share