* Purity is not at all bizarre to the real world. If I have two apples in one pile and three in the other, then merely regarding them as the same pile is (2 + 3) very, very purely. Computers are the bizarre ones!
* "The first two can fail, rely on side effects and the last one is purely a side effect." It'd be much nicer to say that the first two are "side effecting computations with interesting return values" and the third one it the same... except we are not interested in the return.
* "The only pure function is add". I highly doubt that `add` is pure in your example! (1) this wouldn't typecheck in Haskell now if it were and (2) it'd imply that we are just throwing away the result of the addition.
* "the reason you don't see Monads in other languages is because they're not essential to them" I would challenge you to turn this exactly on it's head. The reason you don't see monads in other languages it that they are so essential to them that you cannot perceive parts without the monad.
That sounds more like fmap.
(+) <$> readLn <> readLn
The monadic part only comes into play in the last line:
(+) <$> readLn <> readLn >>= print
It's part of what makes it monadic that the action takes an argument.
Or the whole thing is an applicative if you take at face value his claim that add is pure.
I found that reading about Haskell really helpful for my Java development, and that looking at really simple monads like Optional, and using them in my code, was really helpful for understanding how more complicated monads work. Jumping straight into Haskell's IO monad is really unhelpful.
However, we must chain these into useful programs somehow. Monad is the type name chosen in Haskell for the construct that does this. It's kind of simple if you work it backwards from the syntax. You want to be able to say
The first two can fail, rely on side effects and the last one is purely a side effect. The only pure function is add, which can't work if a or b aren't there. Monads serve as a way to represent the real-world-ness without it seeping into the add function. You can think of each line as a closure getting the next value from the previous line. So readInt returns a Maybe Int. If it returns a Nothing, the next closure is simply skipped. You can insert a check after the add, if you want to, to see if you got Nothing and alert the user, etc. However, the basic idea is that the program does not crash with a NullPointerException. We know what to do if we get Nothing. The add function doesn't need to concern itself with that.Hence, the Monad. It wraps a real world concern around a type (it has a type constructor). You must be able to make one from a concrete value that is unburdened with exceptional state (it has the unit function). You must be able to call pure functions on these monadic values without the side state seeping into the function (it has the bind function).
Edit: the reason you don't see Monads in other languages is because they're not essential to them. You can do stuff in C without Monads. To Haskell, Monads are like the Higgs boson. It's how you bind stuff together.