如何使用parMap与monadic函数? [英] How can I use parMap with a monadic function?

查看:262
本文介绍了如何使用parMap与monadic函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个monadic函数getRate:

I have a monadic function getRate:

getRate :: String -> IO Double

我想将此函数映射到String列表。通常,我只需:

I'd like to map this function over a list of String's. Normally, I would just do:

mapM getRate ["foo", "bar"]

但是由于每次调用getRate都会进行网络调用,因此我想并行映射,以便每个速率都在一个单独的线程或至少在队列之间展开)。我在想像

but since each call to getRate makes network calls, I'd like to parallelize the map so that each rate is fetched in a separate thread (or at least spread out among queues). I'm thinking of something like

parMapM getRate ["foo", "bar"]

但没有parMapM函数,parMap不能使用monadic函数。

but there is no parMapM function and parMap doesn't work with monadic functions.

我可以做什么?

推荐答案

您应该使用Control.Concurrent并同步Control.Concurrent.MVar;例如:

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

部分(fork,join)顺序。在实践中发生的是线程被顺序地在fork和rendezvous漫游通过等待每个线程依次。但是IO同时发生。

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.

请注意,如果你需要调用外部函数,你应该使用 forkOS 而不是forkIO。

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

这篇关于如何使用parMap与monadic函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆