When I was browsing the GHC documentation, I came across the following:<div><br></div><div><span class="Apple-style-span" style="font-family: -webkit-sans-serif; font-size: 23px; "><span class="Apple-style-span" style="font-style: italic; "><span class="Apple-style-span" style="font-size: 13px; ">If the I/O computation wrapped in&nbsp;</span></span><tt style=""><a href="file:///C:/app/ghc-6.10.1/doc/libraries/base/System-IO-Unsafe.html#v%3AunsafePerformIO" style="color: rgb(0, 0, 160); text-decoration: none; "><span class="Apple-style-span" style="font-style: italic; "><span class="Apple-style-span" style="font-size: 12px; ">unsafePerformIO</span></span></a></tt><span class="Apple-style-span" style="font-style: italic; "><span class="Apple-style-span" style="font-size: 13px; ">&nbsp;performs side effects, then the relative order in which those side effects take place (relative to the main I/O trunk, or other calls to&nbsp;</span></span><tt style=""><a href="file:///C:/app/ghc-6.10.1/doc/libraries/base/System-IO-Unsafe.html#v%3AunsafePerformIO" style="color: rgb(0, 0, 160); text-decoration: none; "><span class="Apple-style-span" style="font-style: italic; "><span class="Apple-style-span" style="font-size: 12px; ">unsafePerformIO</span></span></a></tt><span class="Apple-style-span" style="font-style: italic; "><span class="Apple-style-span" style="font-size: 13px; ">) is indeterminate. You have to be careful when writing and compiling modules that use&nbsp;</span></span><tt style=""><a href="file:///C:/app/ghc-6.10.1/doc/libraries/base/System-IO-Unsafe.html#v%3AunsafePerformIO" style="color: rgb(0, 0, 160); text-decoration: none; "><span class="Apple-style-span" style="font-style: italic; "><span class="Apple-style-span" style="font-size: 12px; ">unsafePerformIO</span></span></a></tt><span class="Apple-style-span" style="font-style: italic; "><span class="Apple-style-span" style="font-size: 13px; ">:</span></span></span><br>
</div><div><span class="Apple-style-span" style="font-family: -webkit-sans-serif; font-size: 23px; "><ul><li><span class="Apple-style-span" style="font-style: italic;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-weight: bold;">Use&nbsp;</span></span></span><tt style=""><span class="Apple-style-span" style="font-style: italic;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-weight: bold;">{-# NOINLINE foo #-}</span></span></span></tt><span class="Apple-style-span" style="font-style: italic;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-weight: bold;">&nbsp;as a pragma on any function&nbsp;</span></span></span><tt style=""><span class="Apple-style-span" style="font-style: italic;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-weight: bold;">foo</span></span></span></tt><span class="Apple-style-span" style="font-style: italic;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-weight: bold;">&nbsp;that calls&nbsp;</span></span></span><tt style=""><a href="file:///C:/app/ghc-6.10.1/doc/libraries/base/System-IO-Unsafe.html#v%3AunsafePerformIO" style="color: rgb(0, 0, 160); text-decoration: none; "><span class="Apple-style-span" style="font-style: italic;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-weight: bold;">unsafePerformIO</span></span></span></a></tt><span class="Apple-style-span" style="font-style: italic;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-weight: bold;">. If the call is inlined, the I/O may be performed more than once.</span></span></span></li>
<li><span class="Apple-style-span" style="font-style: italic;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-weight: bold;">Use the compiler flag&nbsp;</span></span></span><tt style=""><span class="Apple-style-span" style="font-style: italic;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-weight: bold;">-fno-cse</span></span></span></tt><span class="Apple-style-span" style="font-style: italic;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-weight: bold;">&nbsp;to prevent common sub-expression elimination being performed on the module, which might combine two side effects that were meant to be separate. A good example is using multiple global variables (like&nbsp;</span></span></span><tt style=""><span class="Apple-style-span" style="font-style: italic;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-weight: bold;">test</span></span></span></tt><span class="Apple-style-span" style="font-style: italic;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-weight: bold;">&nbsp;in the example below).</span></span></span></li>
<li><span class="Apple-style-span" style="font-style: italic;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-weight: bold;">Make sure that the either you switch off let-floating, or that the call to&nbsp;</span></span></span><tt style=""><a href="file:///C:/app/ghc-6.10.1/doc/libraries/base/System-IO-Unsafe.html#v%3AunsafePerformIO" style="color: rgb(0, 0, 160); text-decoration: none; "><span class="Apple-style-span" style="font-style: italic;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-weight: bold;">unsafePerformIO</span></span></span></a></tt><span class="Apple-style-span" style="font-style: italic;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-weight: bold;">&nbsp;cannot float outside a lambda. For example, if you say:&nbsp;</span></span></span><tt style=""><span class="Apple-style-span" style="font-style: italic;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-weight: bold;">f x = unsafePerformIO (newIORef [])&nbsp;</span></span></span></tt><span class="Apple-style-span" style="font-style: italic;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-weight: bold;">you may get only one reference cell shared between all calls to&nbsp;</span></span></span><tt style=""><span class="Apple-style-span" style="font-style: italic;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-weight: bold;">f</span></span></span></tt><span class="Apple-style-span" style="font-style: italic;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-weight: bold;">. Better would be&nbsp;</span></span></span><tt style=""><span class="Apple-style-span" style="font-style: italic;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-weight: bold;">f x = unsafePerformIO (newIORef [x])&nbsp;</span></span></span></tt><span class="Apple-style-span" style="font-style: italic;"><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-weight: bold;">because now it can&#39;t float outside the lambda.</span></span></span></li>
</ul><div><span class="Apple-style-span" style="font-family: arial; font-size: 13px;">Now in Reactive, in e.g. the internal IVar.hs module, I see</span></div><div><span class="Apple-style-span" style="font-family: arial; "><span class="Apple-style-span" style="font-size: large;"><br>
</span></span></div><div><span class="Apple-style-span" style="font-weight: bold;"><span class="Apple-style-span" style="font-family: &#39;courier new&#39;, monospace;"><span class="Apple-style-span" style="font-size: large;">readIVar :: IVar a -&gt; a</span></span></span></div>
<div><span class="Apple-style-span" style="font-weight: bold;"><span class="Apple-style-span" style="font-family: &#39;courier new&#39;, monospace;"><span class="Apple-style-span" style="font-size: large;">readIVar (IVar v) = unsafePerformIO $ readMVar v</span></span></span></div>
<div><span class="Apple-style-span" style="font-family: &#39;courier new&#39;; font-size: 13px; font-weight: bold;"><br></span></div><div><span class="Apple-style-span" style="font-family: &#39;courier new&#39;; font-size: 13px; font-weight: bold;"><span class="Apple-style-span" style="font-family: -webkit-sans-serif; font-size: 23px; font-weight: normal; "><div>
<span class="Apple-style-span" style="font-family: arial; font-size: 13px; ">At first sight this function is not following all the rules described above. Could this cause problems?</span></div><div><span class="Apple-style-span" style="font-family: arial; font-size: 13px;"><br>
</span></div><div><span class="Apple-style-span" style="font-family: arial; font-size: 13px; ">Cheers,</span><br></div><div><span class="Apple-style-span" style="font-family: arial; font-size: 13px; ">Peter</span></div><div>
<span class="Apple-style-span" style="font-family: arial; font-size: 13px; ">&nbsp;&nbsp;</span></div><div><br></div></span></span></div><div><span class="Apple-style-span" style="font-family: arial; font-size: 13px;">&nbsp;</span></div>
</span></div>