How I finally learned what a "monad" is
I struggled. But then I invented it to learn it.

I wrote Clojure, a functional programming language where monads are (implicitly) everywhere, for 3+ years. I learned Haskell for 6+ months, enough time to put together some trivial programs. I knew Common Lisp and Scheme, Python and Ruby. I watched videos and read tutorials and books. I even worked through most of SICP in Shen.

Despite all of this, I still could not understand what a monad was or why it would be useful. What finally made me understand monads was the frustration that came from writing the same code over and over again in Elm.

Elm doesn't have the bind operator in its standard library (>>= in Haskell, some-> in Clojure). So you end up writing code1 like this all the time:

case comments of
   Nothing -> Nothing
   Just ls ->
       case List.first ls of
           Nothing -> div [] [ text "No comments" ]
           Just c ->
               div [ id "first-comment" ] [ text c ]

This is a contrived example but you get the idea. Lots of nested case statements. I wrote a ton of this code until one day, reading the Haskell wikibook, it finally dawned on me that I could define my own bind operator, just like the book says in that link, and clean up a lot of my Elm code. So I did:

(>>=) : Maybe a -> (a -> Maybe b) -> Maybe b
(>>=) m g =
    case m of
        Nothing ->
            Nothing

        Just x ->
            g x

And that was the day I finally grokked what a monad is. After using my Elm version of (>>)= for a while, I began successfully using (>>)= in Haskell code: I could write code using (>>)= and it would compile on the first try.

After implementing bind in Elm, I began to clearly see monads in my Haskell code before the compiler told me: I was becoming fluent in Haskell.

My point is that I only understood it after I implemented it. This reminds me of a quote from Difference and Repetition by Gilles Deleuze (p. 23):

We learn nothing from those who say: 'Do as I do.' Our only teachers are those who tell us to 'do with me', and are able to emit signs to be developed in heterogeneity rather than to propose gestures for us to reproduce. In other words, there is no ideo-motivity, only sensory-motivity.

In related news, I've begun streaming some of my work in Haskell. If you would like to 'code with me', you can join via chat at bsima.me/live or you can pair with me, just send me an email (ben@bsima.me) and we can discuss logistics.

Footnotes:

1

The proper way to solve this is to use the Maybe module in the standard library, of which I was unawares when I did this.