&gt; which means that you can understand the combined program by understanding foo and bar independently. If you can&#x27;t represent the result of bar() as a value x then that breaks down<p>Can you not understand this program by understanding both statements separately?<p><pre><code>    print(&quot;hi&quot;) ; print(&quot;there&quot;)
</code></pre>
Why is that more understandable if the result of print is a value? (obviously, the result of read() is). In any case, describing everything as a value is a PFP idea (note that neither the Lisps nor the MLs do it), that some people like and others (like me) don&#x27;t. In fact, I find the notion of treating every computation as a value (rather than possibly wrapping it as one), a not too great idea. 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>&gt; You only don&#x27;t need to care if the effects commute - and in that case you can actually automatically move them past each other in the monad world<p>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.