How can I use parMap with a monadic function?

僤鯓⒐⒋嵵緔 提交于 2019-12-03 11:42:33

You should use Control.Concurrent and synchronize around a Control.Concurrent.MVar; something like:

fork1 :: (a -> IO b) -> a -> IO (MVar b)
fork1 f x =
  do
    cell <- newEmptyMVar
    forkIO (do { result <- f x; putMVar cell result })
    return cell

fork :: (a -> IO b) -> [a] -> IO [MVar b]
fork f = mapM (fork1 f)

join :: [MVar b] -> IO [b]
join = mapM takeMVar

forkJoin :: (a -> IO b) -> [a] -> IO [b]
forkJoin f xs = (fork f xs) >>= join

Parts of this (fork, join) look sequential. What's happening in practice is the threads are fired off sequentially in fork and rendezvous walks through waiting for each thread in turn. But the IO happens concurrently.

Note that if you need to call foreign functions you should use forkOS instead of forkIO.

There is also a monad-parallel package which provides mapM :: MonadParallel m => (a -> m b) -> [a] -> m [b]. Looking at the IO instance for MonadParallel it does it the same way as in Dominic's answer.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!