2017-02-28 11 views
2

私はコルーチンの生産者と消費者を理解し始めていると思っていますが、私は消費者を集めて最も有用な方法で一緒に生産しています。私はAPIEventのこのプロデューサーを持っている場合は...PureScriptで単一のプロデューサを使用して複数のコルーチンコンシューマに参加するにはどうすればよいですか?

type ID = String 

data APIEvent 
    = Connecting 
    | Fail String 
    | Success String 

derive instance gAPIEvent :: Generic APIEvent 
instance showPeerEvent :: Show APIEvent where show = gShow 

getID :: Producer APIEvent (Aff (avar :: AVAR, console :: CONSOLE, random :: RANDOM)) (Maybe ID) 
getID = produceAff (\emit -> do 
    i <- liftEff $ randomInt 0 10 
    if i < 9 
    then do 
     -- If producer was called with `loop`, the 
     -- producer will restart. 
     emit $ Left $ Fail "Failure to get id." 
     emit $ Right Nothing 
    else do 
     emit $ Left $ Success "id" 
     emit $ Right $ Just "id" 
) 

は、私は、例えば、システムロギングと基本 出力を行う2つのコンシューマに接続する方法を

logFailures :: Consumer APIEvent (Aff (avar :: AVAR, console :: CONSOLE, random :: RANDOM)) ID 
logFailures = forever $ do 
    event <- await 
    lift $ do 
    case event of 
     (Fail message) -> log $ "LOG: " <> message 

showOutput :: Consumer APIEvent (Aff (avar :: AVAR, console :: CONSOLE, random :: RANDOM)) ID 
showOutput = forever $ do 
    event <- await 
    lift $ do 
    log $ "STDOUT: " <> (show event) 

私はjoinConsumersを使用して試してみたが、それはチェックを入力しない それはそう、その後、だけではなくAPIEvent秒の (Tuple APIEvent APIEvent)の消費者を作成します。

main = launchAff $ do 
    v <- runProcess $ 
     (joinConsumers logFailures showOutput) 
     `pullFrom` (loop getPeerID) 
    log $ "Process result: " <> (show v) 

編集:

これは私がなってしまったものです。

main = launchAff $ do 
    v <- runProcess $ 
    transformConsumer 
     (forever $ transform (\i -> Tuple i i)) 
     (joinConsumers logFailures showOutput) 
    `pullFrom` (loop getID) 
    log $ "Process result: " <> (show v) 

出力...

LOG: Failure to get id. 
STDOUT: Test.SO.Fail "Failure to get id." 
LOG: Failure to get id. 
STDOUT: Test.SO.Fail "Failure to get id." 
STDOUT: Test.SO.Success "id" 
Process result: "id" 

答えて

3

あなたが気づいてきたように、あなたはConsumerTupleのSに2 Consumerを組み合わせるためにjoinConsumersを使用することができます。だから今度はConsumerTuple a aConsumeraに変更する必要があります。

transformConsumer 
    :: forall i o f m a 
    . (MonadRec m, Parallel f m) 
    => Transformer i o m a 
    -> Consumer o m a 
    -> Consumer i m a 

しかし、どのようにそこにTransformerを作成するには:あなたはTransformerを使用してConsumerを変換transformConsumer機能を使用することによってこれを行うことができます

?さて、あなたはtransform機能を使用して定期的な機能から1を作成することができます。

transform 
    :: forall m i o 
    . Monad m 
    => (i -> o) 
    -> Transformer i o m Unit 

必要な機能タイプがa -> Tuple a aので、\a -> Tuple a aは仕事を行います。

+0

ご協力ありがとうございます。私の例では、私はプロデューサーにIDを返すようにしました。消費者に 'ID 'を持っている唯一の理由はタイプが並んでいるからです。私は1つも見ませんでしたが、 'Transformer i o m Unit'の代わりに' Transformer i o m a'を返す 'transform'に似た関数がありますか?これはうまくいきませんが、私は '(transformConsumer(liftFreeT $ Transform \ i - > Tuple(Tuple ii)pure))(joinConsumers ...')のようなものが必要なように感じます。タプルの第2要素は値 – Albtzrly

+0

「永遠に(トランスフォームf)」にはそのタイプがありますが、それがあなたが探しているものであるかどうかわかりません –

+0

実際には、それは私が必要なものです!聞くだけで価値を生むことはないので、プロデューサーはプロセスを終了してIDを得る人になります。 – Albtzrly

関連する問題