Now we're going to discuss a new type, and we call this type either. Either is defined as a right or a left. These are two sub-types, or sub-classes if you will, of either, and either doesn't actually come into play. It will just refer to one of these two types.
Let's go ahead and define these types. We'll define right, comment this out here. Right is almost exactly like our definition of box here. We have a map which will take an F, and run F on X, and we'll box it back up in our right here. Then we'll do our little inspector trick so we can see what we're looking at when we're in our console.
I should replace these with these. There we are. Now, if we say our result is a right of three, and we map over that three, maybe add one to it. We console.log this. We should have exactly like our box, right of four. If we go ahead and map and map and map, it will pass our value through just like composition. We've already seen this with box. Now we should have a right of two. There we are.
The difference from box will reveal itself when we define our fold. Let's start by defining our left, though. We make our left type, the other part in either. Now we have our right and we have our left. We'll define exactly the same information, except left is a stubborn little bugger. It will not run the F on the X. It will ignore the F altogether.
When we take a look at this, our right added one and divided by two. If we put this inside a left instead, we will keep our left of three untouched. Left refuses to run any of our requests here. Why is this useful? To get at why this is useful, we will define our fold here and look at some real use cases.
Fold, if you remember from box, removes our value from the type when we run our function. It will drop out of our container type and give us our value back. However, we have two types here. We have a right or a left. Usually, we don't know if we have a right or a left. We don't know which one it is. That's a bit funny to have the right on the left side and left on the right side. Never mind.
If our fold is going to handle either of these cases, it needs to take two functions. If it is the right case, we will run the second function, G here. If it's the left case, we will run the first function. This allows us to branch our code and run the right or left side. Let's go ahead and put this back in a right. We'll say a right of two, and at the end here we will fold it.
If it is a left, we'll say error. If it is a right, we'll return it back. Let's look at this. We should have our result of 1.5. We added 1 to 2 and divided by 2. Now, if we change it to a left, it will ignore all our requests and dump out an error here.
This allows us to do some pure functional error handling, code branching, null checks, and all sorts of concepts that capture disjunction, or the concept of or. That's why we call this either, it's either/or. We can use that all throughout our code.
Let's start with another example here of finding a color. We have this find color function. Find color will take a name, look up this hash, and tell us the hex value for that color. Let's use it here. We'll say find color red. If we look at the results, we will get the hex value for red.
Now, suppose we want to slice this little bit off, this little hash off here, and then say to upper case, this will be our final result. It will be the upper cased FF4444.
What if this function, though, what if we don't have the color? What if we pass in green? What's going to happen is it's going to die. If we look up here we see, "Find color green.slice." It can't call slice of undefined. That's because we never returned any string back. How do we handle this?
We can use either type here to say const found. If we find it -- found -- we'll return a right of it, otherwise we'll return a left of null, it doesn't really matter. Then we'll have to write a return here. Now our find color does not return a string, it returns an either.
With this either type we can't just call slice on it, we'll have to map over it. Let's go ahead and map and take our color. We'll call color.slice, and then we can finish our call here with a fold. If it's an error, we'll return, "no color."
Then, if it is there with a color, we'll call to uppercase on it, just like that. I like to indent these so they're even here, so the E and the C line up like that, but it's up to you.
Let's run this, and we should get, "No color," because it couldn't find green. If we run it again with, say, blue, we'll get our upper cased blue just like that. What's happened here is find color actually tells us whether or not it's going to return a null right here in the signature.
Whenever I call find color, I will get a right or a left back, and I must map over it. I can't just get blindsided by a null in run-time if I pass the wrong color. This is very good.
At the time of programming, we know if we're going to get a null or not. We can map over it. If it's not found, the map doesn't get run because it is a left. If it is found, map will get run, and it runs this part of the fold instead of the left side.
Now, find color has multiple expressions.
We can take this a little step further here. This is very common because we want to return these values instead of nulls from here on out to make our code safer and more predictable. Now, we can say from nullable, and we'll take some X here and say if it is not equal to null, this captures the undefined case as well. We'll return a right of X. Otherwise, we'll return a left of null.
We can rewrite this expression in one go by wrapping it in a from nullable. I have to move this on the other side there. There we are. We have the same results. If it finds it, it puts it into the right. If it doesn't, it goes into the left. This will still work. Let's give it a shot and there we are. If we pass in blues, we do not get the undefined problem. We get no color.