We’re talking here about functions and not methods. For the purposes of this discussion,
a function:

Maps some input a to some output b;

For any input a, there is only one output b (although any b may be mapped to by more than one a);

Does not mutate any state, encapsulated or otherwise, nor does it produce side effects.

Contrast this with a method:

May return something, or not;

May return a different b for an input a;

May mutate state somewhere. May produce side effects.

Let’s look at a simple example function. You want to take your cat to the vet to get a shot for it.

A function from Cat &srarr; Cat

Here we have a simple function from Cat to Cat. We input a cat a on the left,
and we get out an immunized cat b on the right.
It’s important to note that we should not mutate the input cat. What should happen
instead is we input cat a on the left, and get out a brand new cat that is immunized.
Then cat a can be made available for garbage collection.

Cat ready for garbage collection

Of course, there’s no guarantee that people coming into the vet’s office have a cat–or any pet at all,
for that matter. If someone brings a null where we are expecting a Cat, then our nice function from
Cat to Cat doesn’t work so well:

A function from Cat &srarr; Cat null &srarr; Shit

We could have the vet ask everything that comes by if it is null or not. But that is not his job, really. His
job is giving shots to pets. I don’t want all of my functions littered with null checks. Surely, there must be
some way to keep my functions clean and simple, yet make them null-safe as well?

The answer is “Maybe”–more specifically, the “Maybe Functor”.

Note that when you are composing functions, all the functions in the composition have to
fulfill their contracts. If somebody returns a null in there, the whole daisy chain is borked. Consider:

What happens if the call to getElementById doesn’t find anything? You get a null back. Then
that null gets fed to R.prop, and R.prop will fail.

To get around this problem, we can use a Functor.

The same function Cat &srarr; Cat, applied by mapping

A Functor is an object that can be mapped over. By “map” I mean that we can use the same function
from Cat to Cat even though the Cat is now inside a container. Note that in the example above,
The cat is in the kitty carrier, but we we are still using the same immunization function.

This is a big deal, because it allows us keep the null-checking separate from the internal logic of
the function. Now if we get an empty container for input, then there is no reason to even try to apply the
function to its content. We simply get an empty container back.

The same function Cat &srarr; Cat, now null safe!

This example is essentially the “Maybe” functor. “Maybe” let’s you wrap up a function from a to b
so that you can apply it to the contents of the Maybe. Take a look at how we have implemented Maybe in Ramda Fantasy.
You can see that Maybe is a sum type; it is a Just of some value, or it is Nothing.
You can use the direct your composition into the proper channel with something like:

functionfromNullable(x){returnx==null?Maybe.Nothing:Maybe.Just(x);}

Now let’s go back to the capitalize example. We can rewrite that to make use of the Maybe functor:

Now this function is guaranteed to output something–Maybe. If the call to getElementById fails,
we’ll wind up with a Maybe null at the end; otherwise we’ll have a Maybe String. We didn’t have
to guard inside our functions, so that is nice. Instead, we have wrapped up the value we are composing
over inside this container. So we can only access the value by mapping over the container.

(Well, actually, since this is JavaScript, and value is sitting there as a public property on Maybe,
you could just query it. But then you are right back where you started, needing to test for null.)

The Maybe functor only gives us one bit of information: Did we hit a null somewhere along the way or not?
There are other functors that can wrap up more info. The Either functor is either a Left or a Right;
In the Left you can put an error message (or a function, or whatever). If it is a Right, then everything
ran fine.

Promises can also be looked at as functors. Consider:

R.map(function(a){returna+1;},Promise(2));//=> Promise(3)

There are many, many more ways to skin this cat: Validation, IO, Reader, Writer, State, Future …
and of course Array.

R.map(function(a){returna+1;},[10,20,30]);//=> [11, 21, 31]

Arrays are Functors. After all, it’s a container you can map over. Arrays are a bit trickier, though,
since they are intertwined with the notion of iteration.

No reason to stop here, though. We can wrap up the object we’re mapping over in a Functor. We can also
wrap up the function we want to apply inside a container:

Applying a wrapped function to a wrapped value

Once again, it’s the same function from Cat to Cat, but now both function and data are wrapped in containers. The good folks
from Fantasy Land call an object that can handle this
situation an “Apply”, and the function you
use to apply a wrapped function to a wrapped value is ap. For Maybe, that could look like this:

Maybe you are asking yourself, “How do you get into a situation where you have a function inside a container?”
I covered such a situation recently. That article also covers the
ability to create an Applicative, by wrapping up an arbitrary object inside a container via of: