1. "Functors are containers you can call map on. That's it. Seriously."
class Functor f where
fmap :: (a -> b) -> f a -> f b
Historically, fmap in Haskell used to be called map. They gave it a different name so that error messages would appear less abstract when working with lists. fmap (+2) [5] = [7]
2. "you may want to have a function in the container and apply it to value(s) in another container of the same kind. " class Functor f => Applicative f where
-- | Lift a value.
pure :: a -> f a
-- | Sequential application.
(<*>) :: f (a -> b) -> f a -> f b
So at least in Haskell, he describes the sequential application operator but leaves out the ability to lift a pure value to a container value. pure 5 = [5]
[(+2)] <*> [5] = [7]
3. "Monads are containers you can call flatMap on. Again, that's it." class Applicative m => Monad m where
-- | Sequentially compose two actions, passing any value produced
-- by the first as an argument to the second.
(>>=) :: forall a b. m a -> (a -> m b) -> m b
And here's how to use it like a flatmap: [1,2] >>= (\x -> [x + 5, x + 10])
[6,11,7,12]
That's [1 + 5, 1 + 10, 2 + 5, 2 + 10] if you didn't catch that.Usually these also come with some laws to help you reason about the typeclass, but looking purely at the language level it can help to remember that a Functor, Applicative, or Monad are nothing more than a type together with some functions with a certain signature.
I find it's usually more useful for a beginner to just start writing code without all the abstractions. Once they have a pile of code and start to want to clean it up a bit, it's not too hard to start stacking some monad transformers.