2011-12-14 26 views
4

我正在使用John Millikin的枚举器包,并试图创建一些大致等价于Data.Enumerator.Binary.enumHandle的东西,除了它连接套接字本身,然后尝试枚举生成的句柄。困难来自连接不可靠的事实,如果出现问题,我希望重新连接并继续枚举。如何创建一个不断重试的枚举器

我通常希望枚举器是它自己有意义的Monad实例,但由于它是一个函数的类型别名,所以它的monadic行为仅仅是它的输入步骤的读者,看起来并没有多大用处这里。我试图把一些东西扔在一起,只是保持循环的枚举器,使用catchError,但它没有做我所期望的,我无法弄清楚它在做什么,所以我想知道是否有人可以提出一个很好的习惯方法来这个。我很好,只是一个解决方案的骨架,因为显然有很多我已经省略的细节。

任何想法?

回答

3

你可能必须自己写。我不认为它是在任何地方预定义的。然而,这并不难:

enumConnectAgain :: forall b m. MonadIO m => IO Handle -> Enumerator ByteString m b 
enumConnectAgain open step = 
    fix $ \again -> do 
     mh <- liftIO (Ex.try open) 
     case mh of 
      Left (ex :: SomeException) -> again 
      Right h     -> loop h step 

    where 
    loop :: Handle -> Step ByteString m b -> Iteratee ByteString m b 
    loop h [email protected](Continue k) = do 
     mstr <- liftIO (Ex.try $ B.hGetSome h 1024) 
     case mstr of 
      Left (ex :: SomeException) -> enumConnectAgain open step 
      Right str     -> k (Chunks [str]) >>== loop h 
    loop h step = returnI step 

这应该工作。

+0

谢谢!它确实有效,除了我需要检查EOF而不是捕获`hGetSome`上的异常,因为它似乎只是在EOF上返回一个空的ByteString(并且一直这样做)。 – copumpkin 2011-12-15 06:37:13

0

从稍高一点的角度来看,如果你正在做插座,特别是可能不可靠的插座,我不能推荐zeromq够高。

+0

谢谢!它看起来很有趣。不幸的是,我不能选择发件人的协议:( – copumpkin 2011-12-15 14:32:23