2011-12-14 7 views
4

私はJohn Millikinの列挙子パッケージを使用しています。ソケット自体を接続し、結果のハンドルを列挙しようとする点を除いて、Data.Enumerator.Binary.enumHandleにほぼ等しいものを作成しようとしています。難しさは、接続が信頼できないという事実から来ています。何かが間違っていたら、再接続して列挙を再開したいと思います。永遠に再試行する列挙子を作成する方法

私は通常Enumeratorが意味のあるMonadインスタンスであることを期待していますが、関数の型別名であるため、モナドの動作は入力ステップの読者に過ぎません。ここに。 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

ありがとうございます! 'hGetSome'で例外をキャッチするのではなく、EOFをチェックする必要があることを除いて、動作しました.EOF上で空のByteStringを返すように見えるので(無限に続けます) – copumpkin

0

若干高い視点からは、ソケット、特に信頼性が低い可能性のあるものでは、zeromqを十分に推奨できません。

+0

ありがとう!それは面白く見える。残念ながら、私は送信者のプロトコルを選択することはできません:( – copumpkin

関連する問題