&gt; Can you not understand this program by understanding both statements separately?<p>Maybe that one - I&#x2F;O is a bad example, I don&#x27;t really see the value of monads for I&#x2F;O and I don&#x27;t tend to use an I&#x2F;O monad in my programs. Programs I can&#x27;t understand by understanding statements separately are something like:<p><pre><code>    openTransaction()
    writeToDatabase(1)
    rollbackTransaction()
</code></pre>
or<p><pre><code>    val myLog = Buffer()
    myLog :+= &quot;step 1&quot;
    myLog :+= &quot;step 2&quot;
    doSomethingWith(myLog)
</code></pre>
and these cases (database transaction, writer) are things I do find it useful to manage with a monad.<p>&gt; Values are equational, computations are not (even pure ones). It&#x27;s a nice abstraction to have at your disposal, but enforcing it everywhere is too much.<p>You need some way to encapsulate&#x2F;isolate the relevant state of a program partway through running - I think imperative programmers agree that global mutable state is bad. Mostly I see monads as a way to turn global mutable state (whether in the form of global variables, control flow, or something external to the program) into local state, so that you can see which bits of state you need to understand to understand a given line of code.<p>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>&gt; You could, obviously, but when working with continuations, i.e. imperatively, or with Kiselyov&#x27;s freer monads (which are inspired by continuations) you don&#x27;t have to.<p>But will those approaches stop me from tripping myself up when effects <i>don&#x27;t</i> commute? In scalaz-transfigure I do that with the Distributive typeclass - <i>if</i> one effect distributes over another then there will be an instance and you can freely move them past each other, if not then you get a compile error when you try and have to clarify what you want to happen.