&gt; these cases (database transaction, writer) are things I do find it useful to manage with a monad.<p>Yeah, I know, but some of us don&#x27;t :)<p>&gt; You need some way to encapsulate&#x2F;isolate the relevant state of a program partway through running<p>That&#x27;s exactly what continuations do. The question of global mutable state is an orthogonal one.<p>&gt; I think that state has to be equational if we&#x27;re to have any hope of being able to understand programs - if you can&#x27;t say whether this time at line 20 the program is in the same state it was last time at line 20, or a different state from last time, how can you even begin to debug?<p>Well, we <i>have</i> been successfully writing programs like that for a long time. Now, don&#x27;t get me wrong -- the equational abstraction is often very useful, but it has its price, and it&#x27;s not a complete representation of the computation.<p>&gt; But will those approaches stop me from tripping myself up when effects don&#x27;t commute?<p>I don&#x27;t understand. We don&#x27;t trip over ourselves when writing imperative code, and when we do, it mostly has to do with IO or other OS state, and monads won&#x27;t help you there. Linear types (&quot;typestate&quot;) might, but even they are limited.