In principle, I like the way that Haskell enforces purity at the compiler level, and kicks everything impure out to the boundary of the program. I can try to write code that's that clean in another language, but it's always an unstable equilibrium. The compiler won't help me make sure functions stay pure, so all it takes is adding one little bit of statefulness to one function out there, and suddenly, like a virus, everything that calls it, everything that calls anything that calls it, and so on is impure, too.
On the other hand, monads are *@#$% opaque. I can't help feeling that, for many use cases, they are unnecessarily opaque.
At the risk of being branded a heretic, not all assignment makes a function impure. If the function never modifies or uses a mutable variable that's visible outside its scope, while it's visible outside its scope (e.g, it's fine to return that accumulator when you're done with it), and it's more efficient (either in terms of performance or code clarity) to get the job done with some mutation, why not? I'd like a language that doesn't worry so much about what consenting adults do behind closed doors. Rather than not letting me do it at all, I'd rather a language that just helps me make sure I'm doing it in a safe manner that doesn't lead to viral impurity.