To explain like two fundamental rules (we can make wrapper types, and do flatmap) I will:
- Write 5 paragraphs setting up an imaginary scenario involving fantasy elements of aliens, dragons, and a magical kindom where they speak using message boxes
- Introduce basic category theory by starting with what a functor is
- Explain all the effects of a monad in such general terms that it basically amounts to anything and everything - since a function can be anything and do everything and it's just function composition
- Write some snippets of Haskell, and just assume that you're familiar with the syntax
- Talk about how delicious burritos are
I've read more than my fair share of these tutorials, and I'd like to be proven wrong here but I don't think I've ever seen one that explains what the point of these functional constructs (similarly with Applicative etc.) is.
"You can do IO now." So what? I could do IO before that as well.
Very rarely are practical explanations discussed. Even if they are discussed, the treatment is shallow and useless.
From my experience having used Haskell (a long time ago), the main benefit of Monads is the `do` and <- syntax. Once you got your thing to satisfy the Monad interface, you unlocked the nice syntax for writing code. That, and compatibility with transformers.
Whether this is the best thing since sliced bread or not, is left as an exercise to the reader.
Here's my effort: https://m50d.github.io/2013/01/16/generic-contexts
From the very beginning of the article (level 1), I don't see what's wrong with code that looks like the following. Early return seems to fix the "typing this makes me feel ill" part? To me, the following code seems perfectly readable without requiring the reader to know about function composition.
def doFunctionsInSequence1(): Option[Set[Int]] = { val r1 = f1(null) if(r1.isEmpty) { return None } val r2 = f2(r1.get) if(r2.isEmpty) { return None } return f3(r2.get) }