有三種類型,你需要注意的:Client
S可request
但從來沒有respond
,Server
S可respond
但從來沒有request
和Proxy
可以做都。
request
/respond
的參數是要發送的值,並且您綁定的結果分別是響應/請求。這對於request
(你綁定響應)來說很直觀,但是我花了一點時間才點擊了respond
(你需要綁定下一個請求)。它使你的處理步驟整潔的小遞歸函數。 (我最初的直覺是使用Control.Monad.forever
,這對於單向管道很好,但在這裏是錯誤的工具。)
這個問題讓人感到困惑:因爲管道本身是同步的,所以你需要獲得一個初始值來傳遞和把事情踢開。您可以將它傳遞到request
(製作一個拉管道,您與(>~>)
組成),或者將其傳遞到respond
(製作一個推管道,您與(>+>)
組成)。然後你將初始值傳遞給組合管道,給你Effect m r
可以去runEffect
。
我在下面的例子中使用了拉管道,因爲它符合你的API請求隱喻。它實現了這三個階段的雙向管道:
+--------+ Yoken +-----------+ Token +--------+
| |<-------| |<-------| |
| server | | transform | | client |
| |------->| |------->| |
+--------+ String +-----------+ String +--------+
(shouty)
client
生成請求Token
S和打印出的反應。 transform
將Token
s變成Yoken
s(嘿,鍵是彼此相鄰)並將它們傳遞給上游。它還通過提供和追加!
將響應轉化爲喊聲。 server
收到Yoken
s並生成請求的號碼yo
s。
import Data.Char
import Control.Monad
import Control.Monad.IO.Class
import Pipes.Core
import System.IO
data Token = Token Int
data Yoken = Yoken Int
main :: IO()
main = do
hSetBuffering stdout NoBuffering
-- We have to get an initial n outside the pipeline to kick things off.
putStr "N? "
n <- read <$> getLine
runEffect $ server >+> transform >+> client $ Token n
-- The "server" generates a string of "yo"s based on the number inside the Yoken
server :: Monad m => Yoken -> Server Yoken String m a
server (Yoken n) = (respond . concat $ replicate n "yo") >>= server
-- A processing step just for the sake of having one, turn the Token into a
-- Yoken, upcase the string, and append a "!".
transform :: Monad m => Token -> Proxy Yoken String Token String m a
transform (Token t) = do
resp <- request $ Yoken t
next <- respond $ map toUpper resp ++ "!"
transform next
-- Clients request "yo"s, by sending `Token`s upstream.
client :: Token -> Client Token String IO a
client t = do
resp <- request t
n <- liftIO $ putStrLn resp *> putStr "N? " *> fmap read getLine
client $ Token n
非常感謝您的關心,回答我孤獨的問題!我設法自己找到答案感謝http://hackage.haskell.org/package/pipes-2.3.0/docs/Control-Proxy-Tutorial.html – insitu