![](/img/trans.png)
[英]How do I pipe the output string produced by readFile “filename.txt” to Haskell's words function as an argument?
[英]How can I make a Pipe concurrent with Haskell's Pipe library?
我有一些使用Pipes的Haskell代碼:
module Main(main) where
import Pipes
a :: Producer Int IO ()
a = each [1..10]
b :: Pipe Int Int IO ()
b = do
x <- await
yield (x*2)
b
c :: Consumer Int IO ()
c = do
x <- await
lift $ print x
c
main :: IO ()
main = runEffect $ a >-> b >-> c
Pipes.Concurrent教程演示了如何使用多個工作人員以及工作竊取。 我怎樣才能在b
內做類似的事情? 我希望b
使用一定數量的工人同時執行它的工作。
顯然,並發性在這個確切的情況下沒有用,但它是我能想到的最簡單的例子。 在我的實際用例中,我想使用有限數量的工作者同時發出一些Web請求。
編輯:我誤解了你的要求; 你可以在管道內做到這一點,但我不確定它的動機是什么。 我建議建立可重復使用的管道鏈,只使用工人調度它們,而不是試圖在管道內部建立工人。 如果您將其構建到管道本身,那么您將失去任何排序保證,即第一個輸入是第一個輸出。
關於工作竊取的部分是你正在尋找的,這段代碼基本上是從教程中逐字逐句,但讓我們分解它是如何工作的。 這是我們可以做你想做的一種方式:
module Main(main) where
import Pipes
import Pipes.Concurrent
import Control.Concurrent.Async (async, wait)
import Control.Concurrent (threadDelay)
import Control.Monad (forM)
a :: Producer Int IO ()
a = each [1..10]
b :: Pipe Int Int IO ()
b = do
x <- await
yield (x*2)
b
c :: Consumer Int IO ()
c = do
x <- await
lift $ print x
c
main :: IO ()
main = do
(output, input) <- spawn unbounded
feeder <- async $ do runEffect $ a >-> toOutput output
performGC
workers <- forM [1..3] $ \i ->
async $ do runEffect $ fromInput input >-> b >-> c
performGC
mapM_ wait (feeder:workers)
第一行spawn unbounded
來自Pipes.Concurrent,它初始化一個具有輸入和輸出句柄的“郵箱”。 起初它讓我困惑,但在這種情況下,我們將消息發送到輸出並從輸入中拉出它們。 這類似於golang等語言中的推拉消息通道。
我們指定一個Buffer來說明我們可以存儲多少條消息,在這種情況下我們設置無限制的無限制。
好的,所以郵箱已初始化,我們現在可以創建向其發送消息的Effect
。 郵箱通道是使用STM實現的,因此它可以異步收集消息。
讓我們創建一個異步作業來為郵箱提供信息;
feeder <- async $ do runEffect $ a >-> toOutput output
performGC
在a >-> toOutput output
僅僅是正常的管道組成,我們需要toOutput
輸出轉換成管道。 注意performGC
調用也是IO的一部分,它允許Pipes.Concurrent知道在作業完成后進行清理。 如果我們願意,我們可以使用forkIO
運行它,但在這種情況下我們使用async
以便我們可以等待結果稍后完成。 好的,所以我們的郵箱應該異步接收消息,讓我們把它們拉出去做一些工作。
workers <- forM [1..3] $ \i ->
async $ do runEffect $ fromInput input >-> b >-> c
performGC
和以前一樣,但這次我們只是產生了一些。 我們從輸入讀取就像使用fromInput
的普通管道fromInput
,然后在我們鏈的其余部分運行它,在我們完成時清理。 input
將確保每次拉出一個只有一個工人接收它的值。 當所有輸入到output
的作業完成后(它跟蹤所有打開的作業),它將關閉input
管道,工人將完成。
如果你在web-worker場景中使用它,你將有一個主循環,它不斷向toOutput output
通道發送請求,然后產生toOutput output
工作人員,他們從fromInput input
進入他們的管道。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.