[英]Conduit: Multiple Stream Consumers
我寫了一個計算語料庫中NGrams頻率的程序。 我已經有一個消耗一系列令牌並生成一個單一訂單的NGrams的函數:
ngram :: Monad m => Int -> Conduit t m [t]
trigrams = ngram 3
countFreq :: (Ord t, Monad m) => Consumer [t] m (Map [t] Int)
目前我只能將一個流消費者連接到流源:
tokens --- trigrams --- countFreq
如何將多個流使用者連接到同一個流源? 我想要這樣的東西:
.--- unigrams --- countFreq
|--- bigrams --- countFreq
tokens ----|--- trigrams --- countFreq
'--- ... --- countFreq
一個優點是並行運行每個消費者
編輯:感謝Petr,我提出了這個解決方案
spawnMultiple orders = do
chan <- atomically newBroadcastTMChan
results <- forM orders $ \_ -> newEmptyMVar
threads <- forM (zip results orders) $
forkIO . uncurry (sink chan)
forkIO . runResourceT $ sourceFile "test.txt"
$$ javascriptTokenizer
=$ sinkTMChan chan
forM results readMVar
where
sink chan result n = do
chan' <- atomically $ dupTMChan chan
freqs <- runResourceT $ sourceTMChan chan'
$$ ngram n
=$ frequencies
putMVar result freqs
我假設您希望所有接收器都能接收所有值。
我建議:
newBroadcastTMChan
創建一個新的通道Control.Concurrent.STM.TMChan
(stm-chans)。 sinkTBMChan
從Data.Conduit.TMChan
(STM-管道)為您的主要生產商。 dupTMChan
創建自己的副本以供閱讀。 使用sourceTBMChan
啟動將讀取此副本的新線程。 (我沒試過,讓我們知道它是如何工作的。)
更新:收集結果的一種方法是為每個使用者線程創建一個MVar
。 他們每個人都會在完成后將putMVar
的結果putMVar
其中。 和你的主線程會takeMVar
所有這些MVar
S,從而等待每一個線程來完成。 例如,如果vars
是你的MVar
的列表,主線程將發出mapM takeMVar vars
來收集所有結果。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.