<div dir="ltr">Several very elegant FRP approaches are emerging, most visibly FRP.Reactive, which rely on blocking on multiple variables at once, continuing when the *first* of them is available. . . inside an unsafePerformIO, so the beautiful STM &quot;orElse&quot; solution is not available. &nbsp;The current solution is to race threads against each other, and have the one that finishes first kill the other one. &nbsp;This is implemented, for example, in Data.Unamb. &nbsp;However, our empirical tests have shown that the GHC scheduler is not *quite* good enough to handle this efficiently, and ends up introducing too much latency and nondeterminacy.<br>
<br>The <a href="http://hackage.haskell.org/cgi-bin/hackage-scripts/package/data-ivar-0.1">Data.IVar</a> module, just uploaded to hackage, provides an alternative to thread racing as a solution to this problem. &nbsp;It provides *write-once* variables which can be blocked on in parallel, without forking any threads or using STM (so it is safe to use in unsafePerformIO). &nbsp; &nbsp;Example usage from the documentation:<br>
<br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> import qualified Data.IVar as IVar</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> import Control.Concurrent</span><br style="font-family: courier new,monospace;">
<br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> main = do</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> &nbsp; &nbsp;iv &lt;- IVar.new</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> &nbsp; &nbsp;iv&#39; &lt;- IVar.new</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> &nbsp; &nbsp;forkIO $ threadDelay 10000000 &gt;&gt; writeIVar iv&#39; &quot;my spoon is too big&quot;</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> &nbsp; &nbsp;let merger = IVar.read iv `mplus` IVar.read iv&#39;</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> &nbsp; &nbsp;print =&lt;&lt; IVar.nonblocking merger &nbsp; -- most likely &quot;Nothing&quot;</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> &nbsp; &nbsp;print =&lt;&lt; IVar.blocking merger &nbsp; &nbsp; &nbsp;-- waits a while, then prints</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> &nbsp; &nbsp;writeIVar iv&#39; &quot;i am a banana&quot; &nbsp; &nbsp; &nbsp; -- throws error &quot;IVar written twice&quot;</span><br>
<br>Enjoy!<br><br>Luke</div>