In what circumstances is it the best choice? I get the impression that monad libraries in dynamic languages are basically toys, or are written to show off. If I'm wrong, I'd love to see examples of how you used them in a ClojureScript project, why (other than novelty value) you chose them over other approaches like atoms, and how they worked out in practice.
However, your comments regarding monads see a bit off. I've seen the same sentiments expressed elsewhere (i.e. by others), so I think they represent something of a common misunderstanding.
First of all, monads are simply programming patterns which relate a set of values to a set of of functions. 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:
[ Using JavaScript syntax, they can be approximated as... ]
mBind( mBind( mReturn(x), f ), g ) == mBind( mReturn(x), function(x) { return mBind( f(x), g ); } );
// => true
Above, x is any value in the Monad X; f and g are 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.
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, including catching a host of errors at compile time (though that's true regardless of monads).
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.
Sometimes the "monad patterns" 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].
In my case, I'm working on an SCXML-like[3] framework which builds on Google Polymer, core.async and protocol-monads (and core.logic at some point?). By using the State Monad pattern (together with trampolines and core.async channels), the algorithms of SCXML can be implemented in a manner that's not dependent on side effects, instead flowing the "global state" between the computational steps in a manner that is consisent and relatively easy to reason about. To boot, by using channels to link together steps in the "mainEventLoop", time is deliberately yielded back to the CPU, making the framework even more concurrency friendly. The project will be open source soon, and I can follow up with some links to source code once it goes public on GitHub.
You've piqued my interest around the state monad specifically, and I just added a long but promising-looking article on it[1] to my reading queue. However:
> Sometimes the "monad patterns" 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).
I knew this from reading monad tutorials. And yes, certainly there exist useful things that happen to be monads. But I question the usefulness of explicitly pointing that out and saying, "Here's a monad library. I'm going to use this monad library to build X. You can use all the normal monadic functions on X, because it's a monad", as opposed to putting the monad stuff to the side and just building X. What would you gain from building `let` or list comprehensions atop a monad library? Would it be worth the users you'd confuse? The concept of monad is far too abstract to be intuitive to most people, so there is a cognitive cost to making people think about them.
Jim Duey's blog post on the State Monad was helpful to me[1].
I agree that one shouldn't reach for monads just because one finds them interesting or neat, or challenging for that matter.
An analogy: consider that in many cases, `while` and `for` loops are great when looping is what's called for. But there are many times when recursion is more attractive still. But what to do if your language doesn't have TCO, and blowing the callstack is a real concern? Well, then you can use trampolines![2]
Now, trampolines are great, but you don't need to always reach for them. An analysis should be done of the problem at hand, and "the right tool chosen for the task", which may be a simple `while` loop. The same goes for monads. Are there cases where the State Monad makes the most sense among other programming patterns? Yes, I think so. Particularly, when you are trying to model a multi-step and nested-steps computation where the steps are intertwined in such a way that one can easily identify "global state" at work. In that case, the State Monad is a tool that will let you thread the global state through the steps and levels of computation without having to twist yourself into knots doing it some other way AND without relying on unfettered mutability.