This article is flawed at its core: monads do not, in general, compromise type inference and they are <i>not</i> all about sequencing state.<p>Sure, they are used for state and IO, but they can do far more, like nondeterministic programming, continuations or even nothing at all. Ultimately, I would say monads are about composition: they let you define exactly how to compose computations.<p>Additionally, monads do not break type inference. Having a type for every top-label binding is considered good style in Haskell, but it is still optional. I could see this practice being confused for type inference not working. There are of course language extensions that do break type inference in certain cases, and sometimes it is impossible even with the standard language, but it works almost all of the time even with monads.<p>Also, and this is probably just because this article is for years old, it really overstates hire bad Haskell performance is. In my experience, even naively written code runs relatively fast--certainly fast enough for me--in most cases. I believe this has really improved in recent times. Haskell is certainly better in this regard than most other high-level languages.
Two glaring errors in here:<p>> The essence of monads is to use abstract types to enclose a mutable state [...]<p>This is a common misconception, but terribly misleading. The "essence" of monads are the bind and return (or equivalent) functions, allowing decoupled transformations to be performed. The fact that you can write bind and return functions for a type that encapsulates the idea of a side effect is secondary.<p>Would you say "the essence of iterators is to encapsulate infinite sequences"? Infinite sequences happen to be iterable, but to say that they <i>are the essence of</i> iterators is downright wrong. The essence of iterators is traveling through a collection item by item, as defined by the MoveNext/Current (or equivalent) functions.<p>> For one thing, when you use a monad, you get hooked to it: the type constructors of the monad start to appear in the signatures of your function.<p>If you have functions that should have nothing to do with a monad ending up coupled to it, then you're probably doing it wrong. Monadic methods let you "lift" functions, so they don't have to be coupled:<p><pre><code> // bad: unnecessarily coupling your function to a monad
IEnumerable<int> Increment(IEnumerable<int> sequence) {
var r = new List<int>();
foreach (var e in sequence) r.Add(e + 1);
return r;
}
...
var incrementedList = Increment(list);
// good: using monad method to lift a non-coupled function
int Increment(int b) { return b + 1; }
var incrementedList = list.Map(Increment);</code></pre>
Anyone who understands monads is on a class of hard drugs.<p>I'm still looking for someone who can present a cogent explanation of monads using only Python.<p>(I'm willing to replace "Python" in the above challenge with "any language I know well," which would include Python, C, C++, Java, JavaScript, and quite a few others which I won't bother to list here. Notably lacking from this list are Lisp, Scheme, Caml, Haskell, Prolog, Erlang, and most other languages whose view of the world is "weird." NB not that I'm against learning such languages; it's more a matter of available tutorials and time.)
<i>For one thing, when you use a monad, you get hooked to it: the type constructors of the monad start to appear in the
signatures of your function.</i><p>Yup, that's the point![1]<p>[1] Or rather, one of <i>many</i> points.