如何创建一个永远重试的枚举器

时间:2011-12-14 07:07:42

标签: haskell enumerator iterate

我正在使用John Millikin的枚举器包,并尝试创建大致相当于Data.Enumerator.Binary.enumHandle的内容,除了它连接套接字本身,然后尝试枚举生成的句柄。困难来自连接不可靠的事实,如果出现问题,我希望重新连接并重新枚举。

我通常希望Enumerator成为它自己有意义的Monad实例,但由于它是函数的类型别名,因此它上面的monadic行为只是其输入步骤的读者,这在这里似乎没什么用处。我试图将一些东西放在一起,只是使用catchError循环调整枚举器,但它没有按照我的预期进行,我无法弄清楚它在做什么,所以我想知道是否有人可以建议很好的惯用法。我只是一个解决方案的骨架很好,因为很明显我省略了许多细节。

有什么想法吗?

2 个答案:

答案 0 :(得分: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 step@(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

这应该有效。

答案 1 :(得分:0)

从略高的角度来看,如果你正在使用套接字,特别是可能不可靠的套接字,我不能足够推荐zeromq