Having also struggled with Monads before having an <i>aha!</i> moment, I've tried on occasion to help boil it down for those on the search for understanding.<p>The hardest thing to get is that Monads aren't quite as "tangible" (not sure of a better word) as concepts like variable, object, property, instance, function, method. They are essentially relational and require something of a mental leap akin to coming to grips with how JavaScript's event loop is bound up in the control flow of your code, which otherwise proceeds from top to bottom of a .js file; or the rules governing closures and asynchronous function evaluation in this or that language.<p>The following is reprised from one of my HN comments in 2013.<p>-------<p>Monads are <i>programming patterns</i> which relate a set of values to a set of of functions – that's pretty much it! For any monad X, we can say that a function is monadic if it returns a value in the X Monad. The set of values are precisely those such that the following three Monad Laws[1] hold:<p>[ Using JavaScript syntax, they can be approximated as... ]<p>Left Identity<p><pre><code> mBind( mReturn(a), f ) == f(a);
// => true
</code></pre>
Right Identity<p><pre><code> mBind( mReturn(a), mReturn ) == mReturn(a);
// => true
</code></pre>
Associativity<p><pre><code> mBind( mBind( mReturn(a), f ), g ) == mBind( mReturn(a),
function(a) {
return mBind( f(a), g );
} );
// => true
</code></pre>
Above, `a` is (basically) any value, while `f` and `g` are any monadic functions for the same Monad. The definitions of `mBind` and `mReturn` will vary depending on the Monad, but the same laws (and sometimes additional properties) hold for each group of things taken as a whole – the monadic values, monadic functions, and the `mBind` and `mReturn` pair for those values and functions.<p>As you can see, there is nothing special that requires a statically typed language. That being said, if your language is statically typed, and even more so if its type system has advanced capabilities (e.g. Haskell's type system), then the relationships between the monadic values and functions can be leveraged to do a number of useful things, e.g. catching a host of bugs at compile time (though that's true regardless of Monads).<p>If your language is dynamically typed, then you won't get those extra benefits, but you can still take advantage of the fact that Monads can abstract away a great deal of plumbing between various pieces of your program.<p>Sometimes the <i>Monad patterns</i> will appear in a language under another name, or will be used "under the hood" to implement a particular API. Clojure/Script's `let` for example is essentially the Identity Monad; and its `for` is very much akin to the List Monad (the same is true for list comprehensions in other languages). The core.async library involves an inspiring application of the State Monad pattern[2].<p>[1] <a href="http://en.wikipedia.org/wiki/Monad_(functional_programming)#Monad_laws" rel="nofollow">http://en.wikipedia.org/wiki/Monad_(functional_programming)#...</a><p>[2] <a href="https://github.com/clojure/core.async/blob/master/src/main/clojure/clojure/core/async/impl/ioc_macros.clj#L56" rel="nofollow">https://github.com/clojure/core.async/blob/master/src/main/c...</a><p>[&] <a href="https://github.com/clojure/core.async/blob/master/src/main/clojure/cljs/core/async/impl/ioc_macros.clj#L46" rel="nofollow">https://github.com/clojure/core.async/blob/master/src/main/c...</a>