Apply a function in a Maybe context to Maybe inputs

Andy Van Slaars
InstructorAndy Van Slaars

Share this video with your friends

Send Tweet
Published 4 years ago
Updated 3 years ago

Functions are first class in JavaScript. This means we can treat a function like any other data. This also means we can end up with a function as the wrapped value in a Maybe. The Maybe type gives us the ability to apply that wrapped function to other wrapped values, keeping both the value and the function in the safe confines of a Maybe.

Instructor: [00:00] Here we're pulling in maybe, is number, and safe from Crux. We have two maybe numbers defined. We have an add function. We'd like to get the sum of the two numbers with the added safety of the maybe type. The problem is we can't just pass these maybe objects into a function that needs to be applied to numbers. As we can see, our output is not what we'd like.

[00:19] Normally, we'd use the map method to apply a function to a value that's wrapped in a maybe. Let's get rid of this and see what happens when we use map. I'm going to call safe, passing it the add function.

[00:33] Now let's look at the results. We'll see we're getting just not a number. The problem is that our map has got to unwrap the value from safe num one and apply add to it. But add takes two arguments. That second argument is going to get passed as undefined because we don't have a second value available here.

[00:49] Map really only works with functions that have an arity of one. They only take a single argument.

[00:54] We can start to fix this by taking add. We can make that a curried function. We're going to define it as a function that takes in A, returns a function. That return function will take in B. Then it'll add our results.

[01:08] We'll see down here that instead of just not a number, we're already getting just function. This means that add was applied to the value in safe num one. We got a function back. This gives us something we can work with.

[01:19] We're going to come in here. I'm going to chain on a second map. This map is going to unwrap the value in the just which we know is a function. We'll call that fn.

[01:28] Then I'm going to want to apply that function to the value that's in safe num two because this is our second number that we want to add together. I can reference safe num two here. Then I can use map on that to apply the function that was returned from our previous maybe.

[01:45] Now when you look at the result here, our addition is working, but we have two justs because we've nested maybe. We can replace this second map with a call to chain. Now we're getting the expected result. This is giving us our desired result.

[01:58] But it's not the most readable code. We're going to run into this situation more often than you might think.

[02:04] There's actually a method that's specifically designed for applying a function that's wrapped in a maybe to a value that's wrapped in a maybe. Instead of calling chain to get our function and then map over another value, we can actually just call the ap or the AP method here.

[02:20] We can pass it in our second wrapped value. We can pass the safe num two. If we look at the result, we'll see we're still getting our adjust of three. This code is much more readable. We can get rid of this whole code.

[02:34] We can take this a step further. Since functions in JavaScript are first class citizens, we can treat them like any other data which means we can wrap this function in a maybe right out of the gate. Let's define safe add. That's going to be a function that is wrapped in a just. We'll do that just by calling maybe.of on add. Now we've lifted our function into the context of a maybe.

[02:57] Now what we can do is come down here. We can reference safe add. Then we can call ap on that with safe num one. Then we can call ap on it again with safe num two. We'll get rid of that old implementation. We'll look at the results. We'll get our just of three.

[03:20] The Crux library also comes with a utility function that can help us clean this up even more. I'm going to come up here to the top. I'm going to import lift A2 from Crux.

[03:31] Lift A2 is going to do essentially what we've done here where we can define safe add. That'll be a call to lift A2, passing in our curried add function. That's going to give us back a function that we can pass our maybes into like standard arguments.

[03:52] Now we can call safe add. We can just pass in safe num one and safe num two. If we look at the results, we get our just of three. It's worth noting that the two in lift A2 refers to the number of arguments. There's also a lift A3 for functions that require three arguments.

[04:11] Again, the value that we've added here is that all of this is going to run safely. If we ever get an invalid input, we'll see that we're going to get a nothing back. Of course, with a valid value, we'll get a just of our resulting value.

Tre' Codez
Tre' Codez
~ 4 years ago

I've been really wanting to grok liftA2 and I think this is the first post on the net I've discovered that made it approachable. Thanks a bunch!

Andy Van Slaars
Andy Van Slaarsinstructor
~ 4 years ago

I've been really wanting to grok liftA2 and I think this is the first post on the net I've discovered that made it approachable. Thanks a bunch!

Glad I managed to make it approachable, it can be tough to wrap your head around this at first... I know it took me a while.