My take on monads and friends
Vanilla: (a → b) × a → b ┌─┐ ┌─┐ Functor: (a → b) × │a│ → │b│ └─┘ └─┘ ┌─┐ ┌─┐ ┌─┐ Monad: (a → │b│) × │a│ → │b│ └─┘ └─┘ └─┘ ┌───────┐ ┌─┐ ┌─┐ Applicative: │(a → b)│ × │a│ → │b│ └───────┘ └─┘ └─┘
There are plenty of monad tutorials out there, but this is how they make sense to me and maybe it will help you too. There are some minor variations I have made which highlights their similarities and differences.
Notation and Differences
b are type variables and could be replaced by anything like
float or whatever your language gives you. The box around
b (which you might see as
f b in another context, but is not as sightly) are things like lists, objects, or anything that can contain a value of type
→ is a function and
× gives the list of arguments (again, you will probably see
→ being used for this purpose, but we don’t care about currying right now). You might also notice I have some arguments ordered differently.
The four things I’ve given above — vanilla (my made up word on plain function application), functor, monad, & applicative — have a function (
F for shorthand) of 2 arguments, one of which is a function, the other is some value.
F takes the function and applies it to the value. The exact details of how it does this application is not completely specified by the types alone, but gives us a rough idea on what is going on. We’re also missing some way of creating a boxed
a from an
a, but these are not as interesting.
The whole idea is that we have 4 different patterns of applying a function to a value. These patterns save us from writing the same pieces of code in every function we want to operate on a new box.
Even if your language doesn’t let/require you to write down types, these concepts are still there and still worthwhile to become familiar with. I have left out a lot of details and you should go fill those in from somewhere else. But for me, those 4 type signatures capture everything I find important and it looks nice!