2017-02-28 4 views
2

나는 코 루틴 생산자와 소비자를 이해하기 시작하고 있다고 생각하지만, 소비자와 생산물을 유용한 방법으로 함께 모으는 데 가장 힘든 시간을 보내고 있습니다. 나는 APIEvent의 생산을 ...있는 경우PureScript에서 하나의 Producer를 사용하여 여러 동시 소비자에게 어떻게 가입합니까?

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" 
) 

나는 시스템 로깅 및 기본 출력, 예를 들어,을 두 소비자에 연결 할 방법

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를 사용하여 시도했지만, 그 (Tuple APIEvent 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의의에이 개 Consumer 결합에 joinConsumers를 사용할 수 있습니다. 이제 ConsumerTuple a a 인 일반 Consumera으로 변경하는 방법이 필요합니다.

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 함수를 사용하여 일반 함수에서 하나를 만들 수 있습니다 : 당신이 필요로하는

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 '가있는 유일한 이유는 유형이 일치하기 때문입니다. 나는 하나도 보지 못했지만 'Transformer i o m Unit'대신 'Transformer i o m a'를 리턴하는'transform'과 비슷한 함수가 있습니까? 이것은 작동하지 않지만'(transformConsumer (liftFreeT $ Transform \ i -> Tuple (Tuple ii) pure)) (joinConsumers ...'와 같은 것을 필요로하는 것처럼 느껴진다. 튜플의 두 번째 요소는 값 – Albtzrly

+0

글쎄, 영원히 (변환 f)는 그 유형을 가지고 있지만 그것이 당신이 찾고있는 것인지 확실하지 않습니다. –

+0

사실, 그것이 내가 필요로하는 것입니다! 기본적으로 나는 소비자가 필요합니다. 듣고 결코 가치를 내지 않기 때문에 생산자는 그 과정을 끝내고'ID '를 산출 할 사람이 될 것입니다. – Albtzrly