We see three varied examples of where natural transformations come in handy.
[00:00] When might we want a natural transformation? One easy example is something we've seen before. If we have an array of hello world and we want to chain that into a function that will simply split on characters there, any character, we cannot do this because chain does not exist on the array.
[00:23] What we can do instead is do a natural transformation from the array to a list. The constructor here is the natural transformation. Since chain expects the same type of return we can return another list, and there we are. We can log this out and we should get a list of all of the characters in one single list instead of several nested lists.
[00:45] Let's see another place where natural transformations can come in handy. We have our first natural transformation here that takes an array to an either. Then when we run our application we will filter out the large numbers by just getting everyone that's get than 100.
[00:59] We'll map them into larger numbers, we'll multiply them by two, and then we'll grab the first number that is doubled, the first large number that is doubled. If we run this we should get, see we get the right of 800, because we grabbed the 400 and doubled it.
[01:13] Notice, it went through and doubled every single number and then grabbed the first one. We know from our natural transformation laws, which is if we naturally transform some x and map f, that's the same as x map f and naturally transforming the whole thing. If we look at this half it's actually the right hand side of our equation.
[01:31] What we want is to flip it to the left side, because if we grab the first number here and then map larger, it doesn't map every single number near a, it just maps the first one inside the either, because we've transformed it right here.
[01:43] These equations, those, they may seem like common sense, can be mechanically applied, because they always hold for every natural transformation, you don't even have to think about it. Now we can run it and we should have the same answer and we do.
[01:54] That is, two reasons you might use natural transformations. Let's look at one more. This is where things get a little tricky. We're going to have a database here that finds some user and if the id is greater than 2 we'll accept that and return our fake user here. If it is not, we'll return an error.
[02:15] Our fake user has a best friend id. What we're going to do is try to find a user and then find that user's best friend. We have an eitherToTask here ready to go for when we need it. Let's go ahead and give this a shot here. We say Db.find(3) and what we'll do from there is we have a task of an either, let's say it's a right of a user.
[02:38] Here when we map over this we want to grab that user so we have an either and we want to map over that either to get the user out. Then we will finally find the user's best friend id. This is a task holding an either.
[02:55] We'd like to chain this instead of map it, but because we're mapping over the either and returning a task we need up with an either with a task inside it holding the...let's just write right here for concrete types, holding a right of a user.
[03:08] You can see the issue here. We have a task holding a right and that's in a right, and the chain expects us to return a task. Now, we can put another task around it here to make it work out, but things are getting a little bit out of hand. Why don't we go ahead and use our natural transformation?
[03:22] Right after it finds the user here we will simply call map(eitherToTask). Since that's returning another task we can call chain. What that's done is transform this inner either to a task and smush them together with chain.
[03:36] Now, we just get a user directly into this function here, which is much, much nicer to work with. We've converted either to a task so we're no longer working with multiple types here. We can get rid of this annotation. Again, here we can say we have the choice to chain eitherToTask once again because this will return a task holding an either.
[03:56] Finally, we'll fork it out with the error, console.error or the success, console.log. We'll give this a shot. There it is. It found a user with the best friend. If we give it, let's say, 2, the best friend will be too high, and it'll say not found.
[04:15] This is working great. Our eitherToTask actually found their ids and returned the right results even though we've transformed our eithers.
Is eiterToTask available in any libraries?
Is eiterToTask available in any libraries?
It's called an
Async in crocks: https://evilsoft.github.io/crocks/docs/crocks/Async.html#eithertoasync