2012-07-13 3 views
2

작은 메시지 파이프 라인을 구성하기 위해 Pipes-2.1.0 패키지와 zeromq3-haskell 패키지를 사용하고 있습니다. Frames의 마무리를 이해하는 데 문제가 있다는 것을 제외하고는 모든 것이 잘 진행되는 것 같습니다.Pipe-2.1.0 패키지 완성

다음 프레임에서는 두 가지 리소스를 얻습니다. zeromq 컨텍스트 및 zeromq 소켓이 있습니다. 그런 다음 zeromq 소켓에 게시 할 메시지 (ByteStrings 형태)를 계속 기다립니다.

{-# LANGUAGE RebindableSyntax #-} 
{-# LANGUAGE ScopedTypeVariables #-} 

module PipesZeroMQ where 

import   Control.Frame 
import   Control.IMonad.Do 
import   Control.IMonad.Trans 
import qualified Control.Monad   as M 
import   Data.ByteString  (ByteString) 
import   Data.String 
import   Prelude    hiding (Monad(..)) 
import qualified System.ZMQ3   as ZMQ 

type Address = String 

fromList :: (M.Monad m) => [b] -> Frame b m (M a) (M a)() 
fromList xs = mapMR_ yield xs 

publisher :: Address -> Frame Void IO (M ByteString) C() 
publisher addr = do 
    c <- liftU $ ZMQ.init 1 
    s <-liftU $ ZMQ.socket c ZMQ.Pub 
    liftU $ ZMQ.bind s addr 
    liftU $ print "Socket open for business!!!" 

    foreverR $ do 
    bs <- await 
    finallyF (ZMQ.close s M.>> ZMQ.term c M.>> print "ZMQ socket closed") $ do 
     (liftU $ ZMQ.send s [] bs) 
     (liftU (print "Sending message")) 

지금 나는이 시도하는 경우 :

λ> runFrame $ (publisher localAddress) <-< (fromList ["This", "that", "that"] >> close) 

내가이 얻을 :

"Socket open for business" 
"Sending message" 
"ZMQ socket closed" 
*** Exception: ZMQError { errno = 88, source = "send", message = "Socket operation on non-socket" } 

publisher하지만 하나 BytesString를받은 후 확정.

왜 이런 일이 발생합니까?

Pipe-2.1.0에서 Frames를 사용하여 파이널 라이즈를 잘못 이해 한 것에 대해 어떻게 생각합니까?

내가 공격하기 시작하면 밖에서 나무가 우연히 서 있습니까?

foreverR $ do 
    bs <- await 
    finallyF (ZMQ.close s M.>> ZMQ.term c M.>> print "ZMQ socket closed") $ do 
     (liftU $ ZMQ.send s [] bs) 
     (liftU (print "Sending message")) 

당신은 아마 foreverR 루프 외부 finallyF을 배치하고 싶었 : 다음 publisher 기능을 작성할 때

답변

3

당신은 실수를

당신이 그것을 쓴 방법은, 그것은 각각의 후 확정
finallyF (...) $ foreverR $ do 
    bs <- await 
    liftU $ ZMQ.send s [] bs) 
    liftU (print "Sending message") 

보내십시오, 그래서 그것은 정확히 당신이해야 할 일을하고 있습니다. finallyF은 완료자가 성공적으로 또는 실패 할 경우 종료자를 호출합니다. 루프가 결코 어쨌든 종료하지 않기 때문에 또한,이 경우 catchF을 사용할 수 있습니다 각 전송 후에 파이널 라이저가 실행되지 않도록 또는

catchF (...) $ foreverR $ do 
    bs <- await 
    liftU $ ZMQ.send s [] bs) 
    liftU (print "Sending message") 

을, 당신은 루프 내에서 그것을 유지하지만 catchF로 전환 할 수 : 당신이 파이프를 기반으로 zeroMQ 라이브러리를 작성하는 계획하는 경우에 나는 새로운 향상된 기능의 많은 다음 릴리스에서 일반 모나드로 다시 프레임을 반환 할 계획입니다 있기 때문에

foreverR $ do 
    bs <- await 
    catchF (ZMQ.close s M.>> ZMQ.term c M.>> print "ZMQ socket closed") $ do 
     (liftU $ ZMQ.send s [] bs) 
     (liftU (print "Sending message")) 

, 저와 연락을 유지 리소스를 닫고 다시 초기화하는 기능과 같은 기능에 대해서도 마찬가지입니다. 내게 연락하려면 사용자 이름 Gabriel439로 gmail.com 주소를 사용하십시오.

+0

가브리엘에게이 질문에 대한 답변과 훌륭한 파이프 패키지에 감사드립니다. – Eric

+0

@ Eric 나는 첫 번째 또는 두 번째 예제가 후자의 것이 아무것도 잡히지 않기를 원한다는 것을 언급하는 것을 잊어 버렸다. 'catchF'와'finallyF'는 파이프 종료를 인터셉트 만 합니다만, 기본 모나드에서만 액션을 실행할 때 다른 파이프가 끝날 확률은 없습니다. –