2017-06-08 3 views
0

双方向のProxyインスタンスが理想的な問題をモデル化するためにパイプを使用しようとしています。双方向パイプの使い方は?

api logic 
    | ^
    | | 
    v | 
    A A' 
layer 1 
    B B' 
    | ^
    | | 
    v | 
layer 2  

はとても基本的に、私はlayer 1を持って双方向の変圧器である:基本的に、私は以下のアーキテクチャのようなものを持っています。モデルはプルベースなので、メッセージストリームの変換はlogicコンポーネントからのプルによってトリガーされます。

だから私は、アイデアが​​が何らかの変換A -> Bが、その後、レイヤ2からB'を使用していますB' -> A'を適用しlogicにそれを渡すん、apiからAを引っ張るということで、layer1 :: Proxy A' A B' B m xを持っている必要があります。明らかではないが、何

は次のとおりです。私はArequestBの対応方法を知っているが、どのように私はB'からA'を作るのですか? Client sがrequest決してrespondServer sがrespond決してrequestProxyが行うことができますすることができますすることができます:3つのタイプのあなたが意識する必要があります

答えて

2

ここに収まるライブラリ内のすべてのコンビネータを...そこにいないようですどちらも。

request/respondへの引数は送信する値であり、バインドした結果はそれぞれ応答/要求です。これはrequest(応答をバインドする)の直感的な意味を持ちますが、respondの次のリクエストをバインドする)をクリックするまで少し時間がかかりました。それはあなたの処理ステップをきれいに再帰的な機能にさせます。最初の本能はControl.Monad.foreverでしたが、一方向パイプの場合はうまくいきますが、間違ったツールです。

混乱を招くビット:パイプ自体が同期しているため、渡すために初期値を取得する必要があります物事をキックオフする。 ((>~>)で構成するプルパイプラインを作成する)requestに渡すか、respond(>+>)で構成するプッシュパイプラインを作成)に渡します。次に、初期値を合成パイプラインに渡します。Effect m rrunEffectになります。

APIリクエストメタファーに合っているので、私は以下の例でプルパイプラインを使用しました。これは、この三段双方向パイプラインを実装しています

+--------+ Yoken +-----------+ Token +--------+ 
|  |<-------|   |<-------|  | 
| server |  | transform |  | client | 
|  |------->|   |------->|  | 
+--------+ String +-----------+ String +--------+ 
           (shouty) 

clientToken秒を要求生成し、応答を出力します。 transformTokenYokenに変換します(ちょっと、キーはお互いに隣り合っています)。それはまた、アップケーシングと!を追加することによって応答を叫びに変えます。 serverYokenを受信し、要求された番号yoを生成します。

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 
+0

私の孤独な質問にお世話になりました。私はhttp://hackage.haskell.org/package/pipes-2.3.0/docs/Control-Proxy-Tutorial.htmlのおかげで自分自身で答えを見つけることができました – insitu