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 "orElse" solution is not available. The current solution is to race threads against each other, and have the one that finishes first kill the other one. This is implemented, for example, in Data.Unamb. 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.
The Data.IVar module, just uploaded to hackage, provides an alternative to thread racing as a solution to this problem. 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). Example usage from the documentation:
import qualified Data.IVar as IVar
import Control.Concurrent
main = do
iv <- IVar.new
iv' <- IVar.new
forkIO $ threadDelay 10000000 >> writeIVar iv' "my spoon is too big"
let merger = IVar.read iv `mplus` IVar.read iv'
print =<< IVar.nonblocking merger -- most likely "Nothing"
print =<< IVar.blocking merger -- waits a while, then prints
writeIVar iv' "i am a banana" -- throws error "IVar written twice"
Enjoy!
Luke