JavaScript Monads part 3

Mbedingfield
3 min readDec 4, 2022

--

Welcome back, hopefully you have been following this series that starts here.

We are going to pick up where we left off. We saw that this Maybe monad can do something, but what can it really do? Let’s take a look at this with some tests. Let’s get rid of this code that we wrote:

const a = {
b: {
c: 'my code',
},
};

const appendString = (obj) => obj.b.c + ' works properly';
const result = appendString(a);
console.log(result);

Now, let’s add some functionality to this maybe so we can actually start to do things:

const maybe = (x) => ({
isNothing: () => isNullOrUndef(x),
extract: () => x,
map: (f) => (!isNullOrUndef(x) ? Maybe.just(f(x)) : Maybe.nothing()),
});

We added map, and the way that this is going to work is that if we try to map over something that is actually mappable, we just return a new Maybe and execute the map function over the value that is being held by our Maybe. If the value inside the Maybe can’t be mapped, we just return a Nothing, so this way, nothing is going to break.

Now, let’s modify our testing like so:

const maybeNumberOne = Maybe.just(1);
const mappedJust = maybeNumberOne.map((x) => x + 1);
console.log(mappedJust.extract());

const maybeNumberTwo = Maybe.nothing();
const mappedNothing = maybeNumberTwo.map((x) => x + 1);
console.log(mappedNothing.extract());

Then let’s remove this code:

console.log('maybe.just is nothing?', maybeNumberOne.isNothing());
console.log('maybe.nothing is nothing?', maybeNumberTwo.isNothing());

Now, we should see this in our console:

Let’s start to break this down a little bit. When we mapped over the first Maybe that was holding a 1, we just added one to it. When we tried mapping over the second Maybe that was holding nothing, nothing broke. All’s well that ends well I suppose.

Now that we have mapping capabilities at our disposal, let’s bring back our original problem and see if this Maybe thing can be a fix for that.

const a = {
b: {
c: 'my code',
},
};

const maybeA = Maybe.just(a)
.map((a) => a.b)
.map((b) => b.c)
.map((c) => c + ' works perfectly')
.extract();

console.log(maybeA);

Now your console should be printing out that your code works perfectly again. Now we can run our tests and see what happens if we remove c

const a = {
b: {},
};

You should just see null in the console. Now if we remove b

const a = {};

Even though we have no b, our code still doesnt break. We have seen previously, that our code would have blown up the console, but now everything is safe. In our next post, we are going to look at using point free coding with this monad.

Continue on with this series by clicking here to see the next post.

--

--