We learn the formal definition of a functor and look at the laws they obey.
I have some news for you guys. You've been using functors. [sound effect] I know.
Now, the definition of a functor is any type with a map method. It must obey a few laws. It must act correctly so we can reason about and build upon these principal things. These laws are as follows.
Any type f of x, some functor holding x, when we map f over it and then we map g over it, that should be the same as running map once over it by saying first run f, then run g.
This law is the law that preserves function composition while mapping. We have that intuition. As we map over arrays, if you map and you map and you map, it's often quite obvious that you can map once and run all those functions together.
Let's go ahead and examine and prove this first law. Let's go look at box. We'll say const result here. If we have a box say of squirrels, ha ha, a fun box of squirrels, when we map over this, let's say we'll take squirrels.substringfive.
Then, we map again to uppercase it. Let's give ourselves some room here. Just ahead and call map two uppercase on our squirrels. Two uppercase, there we are. We just log this.
Let's call this result one. This should be exactly the same as just calling two uppercase right there in the one map. We'll call this result two. Let's go ahead and compare these two in the output here. We've got to come in data, code there. There we are. They are equal here.
We see that this preserves function composition. If I was to take squirrels and call substring five into uppercase, this is function composition. As you see in the box with map, it is preserving this exact concept. It is fusing maps together into one to preserve this function composition.
One thing to mention before we go into the second law is this works for any type here. We could use our write here. Here's write. Those are indeed equal. Here's left. Even though the maps don't run, they are still equal. This is true for every functor.
In fact, it must be true for it to be a functor. Same with task. Therefore, all the types we see on the screen, list, map, right, left, eye the task, box, are all functors, because they have a map method that obeys these laws.
The second law let's just examine really quickly. We will take a new function here. Let's call it ID. It takes an x and returns back that x. If I have a functor x as the second law here and I map ID over my type, that will be the same as just calling ID on f of x.
Let's go ahead and try this one out. We have a result here. We'll do res one. Again, we'll just use box for simplicity. We'll just go ahead if we have a box of crayons and we map ID over that, that is the same as calling ID on box of crayons. Let's go ahead and space that right in there. If we look at this, we get the same result.
Again, we can do this with any type here. Let's go ahead and do it with a list of crayons. Of course, it is the same because these are functors.