Instructor: 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.
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 num.map, passing it the add function.
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.
Map really only works with functions that have an arity of one. They only take a single argument.
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.
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.
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.
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.
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.
But it's not the most readable code. We're going to run into this situation more often than you might think.
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.
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.
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.
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.
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.
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.
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.