*This is part 4 of a series on Implementing a (kinda) fantasy land compliant Maybe type. For part 1, go here, part 2 is here and part 3 can be found here*

Last time, we ended up with a **Functor** instance on our **Maybe**! This time, we’ll go right ahead and add a **Apply** instance.

## Ap Ap

If we look at the spec, we get the following:

An instance of Apply must implement an

`ap`

method:`ap :: Apply f => f a ~> f (a -> b) -> f b`

So, if we have an `Apply a`

, then we can do `a.ap(b)`

to use the `ap`

function. And there are a couple of rules:

`b`

must be an**Apply**of a function, and the same type of**Apply**as`a`

.`ap`

must apply the function in Apply`b`

to the value in Apply`a`

.

Wait, what? Right. Same reaction here at first, so let’s try to unwrap the type definition first:

`ap :: Apply f =>`

➡ name of the function and a type restriction. This means that every time we see an`f`

in the signature, we know that`f`

must be an Apply.`f a ~>`

➡ Remember the squiggly line? It means that this function (`ap`

) is a method of an Apply of`a`

.`f (a -> b) ->`

➡ This is the argument that`ap`

gets. And it means what is stated in rule 1, the argument must be an Apply of a function (that’s what`(a -> b)`

represents, a function that takes an`a`

and returns a`b`

.`f b`

➡ Return type of the function. An Apply of the result of applying the function that came before (`a -> b`

).

If it still looks a bit fuzzy, do not panic! This one’s weird, specially for those of us who don’t come from a functional background. Let’s keep moving and hope implementing the function clears it up a bit.

## Applying on

While implementing our **Functor** instance, we decided that `Nothing.map = Nothing`

. So, it makes sense that thats the same behaviour we provide for `ap`

.

Here are some tests and the implementation that makes them pass:

`// Nothing.ap === Nothing`

it("should always return Nothing when called on a Nothing", () => {

const actual = Nothing()

.ap(Just(x => x))

.equals(Nothing());

expect(actual).toBe(true);

});

//Just.ap(Nothing) === Nothing

it("should always return Nothing when called on a Just with a Nothing as argument", () => {

const actual = Just(9).ap(Nothing()).equals(Nothing());

expect(actual).toBe(true);

});

const Nothing = value => ({

value: () => "Nothing",

isNothing: () => true,

isJust: () => false,

equals: other => other.isNothing(),

concat: other => other,

map: fn => Nothing(),

ap: other => Nothing(),

constructor: Maybe,

toString: () => "Nothing",

inspect: () => "Nothing",

instances: ["Semigroup", "Monoid", "Functor", "Apply", "Applicative"],

});

const Just = value => ({

value: () => value,

isNothing: () => false,

isJust: () => true,

equals: other => (other.isNothing() ? false : fantasyEquals(Just(value), other)),

concat: other => (other.isNothing() ? Just(value) : Just(fantasyConcat(value, other.value()))),

map: fn => Just(fantasyMap(fn, value)),

ap: other => {

if (!other.isJust()) return other;

},

constructor: Maybe,

toString: () => `Just(${value})`,

inspect: () => `Just(${value})`,

instances: ["Semigroup", "Monoid", "Functor", "Apply", "Applicative"],

});

*Note: if you’re wondering where the heck that .equals came from, I’ll explain later! Really, I will! For now, you’ll just have to trust me when I say it was necessary and I was tired of all the toString hacks.*

Now, for the second part in which we have a `Just`

and the value inside of `ap`

is another `Just`

.

`it("should apply the function inside of the argument to the value of the Just being called on, and return a Just of the result", () => {`

const expected = Just(3).value();

const actual = Just(9).ap(Just(Math.sqrt)).value();

expect(actual).toBe(expected);

});

const Just = value => ({

// …

ap: other => (other.isJust() ? Just(fantasyMap(other.value(), value)) : other),

// …

});

What happened here? Let’s go step by step:

`other.isJust() ?`

➡ we inverted the conditional to ask first if the argument we got is a`Just`

instead of the opposite. And we’ll be using the ternary operator in the function.`Just(fantasyMap(other.value(), value))`

➡ first part of the ternary. If the condition is true, then this gets returned. And what’s happening inside, is basically the same as`map`

, only we replace the function with our argument’s value (remember, the argument must be an Apply of a function) . We also re-wrap it in`Just`

like we did in`map`

because our function tells us the result must be of the same Apply type as what it was called on.`: other`

➡ if our argument is not a Just, then it’s a Nothing. And if it’s a Nothing, we return Nothing, which is the same as returning the argument itself.

And that’s mostly it. Not too shabby if I may say so myself.

## Ain’t no Algebra without properties

Of course there are properties that we must fulfil. Here’s the one for **Apply**:

`v.ap(u.ap(a.map(f => g => x => f(g(x)))))`

is equivalent to`v.ap(u).ap(a)`

(composition)

This one’s… verbose. But what it’s basically saying is that applying twice is the same as applying once with the composition of the 2.

And here’s how we write the property and the test for it:

`const applyComposition = (a, u, v) => v.ap(u.ap(a.map(f => g => x => f(g(x))))).equals(v.ap(u).ap(a));`

const maybeFnArb = jsc.fn(jsc.string).smap(

Just,

x => x.value(),

y => y.toString()

);

it("should fulfil the composition property", () => {

expect(jsc.checkForall(maybeFnArb, maybeFnArb, maybeArb, applyComposition)).toBe(true);

});

`maybeFnArb`

is an arbitrary function that must return an arbitrary `Just(string)`

.

That’s it, done, finito! Now, you may be wondering:

## Why in heaven’s name

I know, wasn’t `map`

enough? Why do we want this instance, why would we need to have our function wrapped inside of the `Maybe`

? Well, I’ll be the first to admit, you might never need this, especially in normal day to day non FP Javascript. I know I haven’t yet. But the theory behind it is quite sound, hear me out:

Sometimes, you might want to apply a function you don’t know exists. So, the value of your function could either be wrapped inside a `Just`

or be a `Nothing`

. And you don’t want your code to blow up, which is exactly what it would do if you used `map`

in such a situation. So, `ap`

and the **Apply** algebra are intended for those kinds of situations, where you don’t know wether that function is there or not. It’s all about feeling more confident in your code’s ability to not blow up, or at least that’s how I see it.

So:

- Semigroup ✅
- Monoid ✅
- Functor ✅
- Apply ✅
- Applicative up next! (With a little Setoid detour).