All the library overhead is distracting and confusing, taking away from the core concepts.

Also, doing it all in one giant stack is also bad. If you want to show people what monads can do, it's better to have a bunch of small little nuggets of idea, isolated from one another, so the reader can get a sense of whats going on in each case, and how each case is, in fact, a monad, and why this monadicity is what makes it easier and more beautiful to wrote these things.

I felt the point of the article was to examine applying monads without regard for what a monad is. "Who cares what it is, here's what you do with it."

In light of that, it worked for me. It succeeds as a tour of a variety of monads and how you can combine them to accomplish concrete tasks.

What isn't clear to me is how the stacking works without monadic code having to worry about explicitly pushing functions into one monad or another remains obscure, and why it is we suddenly have to sprinkle in a liftIO. But the article makes clear that it's intentionally hand-waving there, and the point of the article is "pay no mind to what's behind the curtain, but behold! Haskell's got some marvellous curtains from this side."

Maybe only slightly related, but Monads are very similar structurally to the continuation passing style in how they model computation using one will typically make the other easier to use. A fully monadic factorial bears great semblance to one written in CPS:

Both monads and CPS are a very similar way of turning "normally" written expressions inside out. The whole idea of normal return values to a surrounding context is something that was imported into computer programs to make them look like normal mathematical expressions but it actually doesn't serve to build a good understanding about a sequenced process like computation.