In stream processing frameworks this is a (common) non-deterministic merge
operation.
Because it's nondeterministic it would need to happen in IO:
parCompletionOrder :: [a] -> IO [a]
But it can be nonblocking (returns immediately, and "lazy IO" happens in
the background).
The Chan library has
Conal Elliot did something like this for his FRP system in the paper
Push-Pull Functional Reactive Programming [1]. It involved a hack in
which unsafePerformIO was used to spawn two threads to evaluate two
events for occurrences, and return whichever returned first.
Recall though, that monads aren