Performing an action which may return other actions to be performed, concurrently I have a program which, at its core, involves repeatedly performing an action on some value, and based on that action also returning a list of new values to perform that action on. The pure version of my function is:

recurse :: (a -&gt; [a]) -&gt; a -&gt; [a]
recurse f a = a : concatMap (recurse f) (f a)


Which can be used for things like tree traversals, such as:

data Tree a = Node [Tree a] | Leaf a

f (Node ls) = ls
f (Leaf x) = []

recurse f (Node [Leaf 10, Node [Leaf 20, Leaf 3], Leaf 12]) 
  == [Node [..], Leaf 10, Node [..], Leaf 20, Leaf 3, Leaf 12]


This function becomes more useful if you generalize it to an arbitrary monad:

recurseM :: Monad m =&gt; (a -&gt; m [a]) -&gt; a -&gt; m [a]
recurseM f a = do
  xs &lt;- f a
  rests &lt;- mapM (recurseM f) xs
  return $ a : concat rests


But what I really want to do with it is make it asynchronous, because (a) I do not care about the order the results come in, and (b) I anticipate the actions themselves taking a while waiting on network operations. Here is my first pass at writing the async implementation (without results) of the above functions:

recurseAsync_ :: (a -&gt; IO [a]) -&gt; a -&gt; IO ()
recurseAsync_ f a = do
  xs &lt;- f a
  mapM_ (forkIO . recurseAsync_ f) xs


While this works, I'm unfamiliar enough with concurrency in general and in Haskell specifically to be sure that this will actually run all of the code I want in parallel. Also, I'm unsure of how to make this code return the results, but that isn't really the important part of the code.
I think yours works, but async specializes in this stuff.

recurseAsync :: (a -&gt; IO [a]) -&gt; a -&gt; IO [a]
recurseAsync f a = do
  xs &lt;- f a
  fmap concat $ mapConcurrently (recurseAsync f) xs