During the long break between my posts in the end of last year I pondered how a visual representation for all that Functor, Monad, Applicative stuff would look like. I myself are a visual thinker, i.e. thinking always involves images moving and rotating through my head. Visual representation now helps to get an imagination of concepts and make thinks more clear, at least to me.
Now, this is the first post where I try to present a visual representation. Fiddling with images on a computer now is not my kind of art, and time is scarce. But I didn’t want to wait longer to present a first result, so bare with some lack of aesthetics in the pictures.
This post is about Functors, or more precisely the map method, and is especially related to my post: Functors, Monads, Applicatives – different implementations . It is therefore recommended that you (re)read that one, and best its predecessor, before. (I thought about changing those posts to include the images, but decided against it).
Now, it all starts with an instance of class MyBox[A] and a function from A to B, in this case a MyBox[String] and a function String=>Int :
As we have seen in the post referenced above, map can be implemented as a standalone function or as a method on class MyBox. We will begin with the latter. Let us now turn the MyBox image slightly in our direction:
We now have this MyBox thing and the function. Let us now think about the function to be some sort of pipe that can take a string on one end and outputs an integer on the other end. Calling the map method/function is now comparable to plumbing the pipe to the MyBox thing:
Ok, here we “put the pipe on it”. Beneath the picture you see three different ways to implement map, and the first one in black is the one this image is about .
When we now let the plumbing do its work due to the map method, it not only gives the result value of the mapped method, but this value is wrapped in a MyBox again.
So this is the complete picture of this scene:
This is very easily grokkable, and holds for may cases where map is implemented as a method on a class. For example for Option, or for collections:
Here is how it is applied maybe to a List. The original box has many values, and the plumbing puts each into the pipe and produces a similar box with the output values.
That was easy and matches mostly the first experiences we make with map in Scala. But the original notion presented in the first post was more according to this:
Map is here thought as being a function that converts (lifts) a function from A to B into a function from M[A] to M[B]. Fed with a function String=>Int, it produces a function MyBox[String]=>MyBox[Int]. And this “lifting”, presented in the right way, seems more in the line of thinking of category theorists.
We now have a world with some values of some types on the left, together with functions between those types. In the picture the types are String (value “hello”) and Int (value 5), and the function is what you see in the red box. In this imagination we consider the function map now being a pipe, in fact one which moves the function from the left side world to the right side world, where any value is hidden in a box of some type (here: MyBox). And as surely as the original function could work with “hello” and produce the 5, the transfered function can handle a “hello” in a MyBox and produce a MyBox with a 5 in it.
Hopefully you found this representation of map with images as useful as I did. I try to use this way of representation in further posts, perhaps even inline in the “Functors, Monads, Applicative” series.