# 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 -> [a]) -> a -> [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 => (a -> m [a]) -> a -> m [a]
recurseM f a = do
xs <- f a
rests <- 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 -> IO [a]) -> a -> IO () recurseAsync_ f a = do xs <- 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. ## 1 Answer I think yours works, but async specializes in this stuff. recurseAsync :: (a -> IO [a]) -> a -> IO [a] recurseAsync f a = do xs <- f a fmap concat$ mapConcurrently (recurseAsync f) xs