在Pipes-2.1.0包中完成

时间:2012-07-13 23:29:37

标签: haskell monads categories monad-transformers iterate

我正在使用Pipes-2.1.0包和zeromq3-haskell包构建一个小消息管道。除了我无法理解Frames的最终确定之外,一切似乎都进展顺利。

在下面的框架中,我获得了两个资源;一个zeromq上下文和一个zeromq套接字。然后我不断等待消息(以ByteStrings的形式)在zeromq套接字上发布。

{-# 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后确认。

为什么会这样?

我对使用Pipes-2.1.0中的Frames最终确定有什么误解?

如果我开始攻击外面的树是否有机会?

1 个答案:

答案 0 :(得分:3)

编写publisher函数时出错:

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

您可能希望finallyFforeverR循环外部放置

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,以便在每次发送后终结器不会运行:

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

另外,如果您打算根据管道编写一个zeroMQ库,请与我保持联系,因为我计划在下一个版本中将帧返回到普通的monad,并对功能进行了许多新的增强。 ,例如关闭和重新初始化资源的能力。要联系我,请使用我的gmail.com地址和用户名Gabriel439。