title: Can side effects be contained with descriptions of impure computations and lazyness?
body: <p>FP tries to separate the pure from the impure realm of a program by merely describing impure computations and running them later. I've been wondering for quite some time whether this means that the harmful implications of side effects are also just deferred.</p>
  <p><code>Aff</code>'s type creates descriptions of impure array computations by wrapping them into thunks. The results of once perfomed <code>Aff</code> computations are shared, i.e. <code>Aff</code> has lazy semantics:</p>
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>// product type constructor
  
  const record = (type, o) =&gt;
    (o[type.name || type] = type.name || type, o);
  
  // Arr type
  
  const Arr = thunk =&gt; record(
    Arr, {get run() {delete this.run; this.run = thunk(); return this.run}});
  
  // Functor
  
  const arrMap = f =&gt; tx =&gt;
    Arr(() =&gt; f(tx.run));
  
  // Applicative
  
  const arrAp = tf =&gt; tx =&gt;
    Arr(() =&gt; tf.run(tx.run));
  
  const arrOf = xs =&gt; Arr(() =&gt; xs);
  
  // impure functions
  
  const arrPush = x =&gt; xs =&gt; (xs.push(x), xs);
  const arrShift = xs =&gt; (xs.shift(), xs);
  const arrGet = i =&gt; xs =&gt; xs[i];
  
  const arrAppend = xs =&gt; ys =&gt;
    (xs.push.apply(xs, ys), xs);
  
  // MAIN
  
  const ta = arrOf([1,1]); // [1,1]
  const tb = arrOf([2,2]); // [2,2]
  const tc = arrMap(arrPush(10)) (ta); // [1,1,10]
  const td = arrMap(arrPush(20)) (tb); // [2,2,20]
  
  const te = arrAp(
    arrMap(arrAppend) (tc)) (td); // [1,1,10,2,2,20]
  
  const tf = arrMap(arrShift) (te); // [1,10,2,2,20]
  const tg = arrMap(arrGet(1)) (tf); // 10
  //                            ^^ A
  const th = arrMap(arrGet(4)) (tf); // 20
  //                            ^^ A
  
  const main = arrAp(
    arrMap(x =&gt; y =&gt; x + y) (tg)) (th);
  
  console.log(
  main.run); // 10 + 20</code></pre>
  </div>
  </div>
  </p>
  <p>Even though <code>tf</code> is run twice (<code>A</code>) the side effect only occurs once. If I'm not mistaken, <code>Aff</code> is capable of stopping side effetcs from interfering with idempotency.</p>
  <p>But what about the associative or commutative property? Side effects introduce time into code and thus the order of more than two composed operations or the order of operands should matter, right?</p>
  <p>Unfortunately I couldn't find an example to prove that even with <code>Aff</code> mutations are harmful. I'm pretty sure there are some and this is just a case of implementation blindness..</p>