1

私は次のことをしようとしています:

sourceIRC
  :: (MonadBaseControl IO m, MonadLogger m)
  => NetworkSettings
  -> Producer (ConnectionT m) Message
sourceIRC networkSettings = do
  withConnectionForever networkSettings $ \socket -> do
    bracket (liftBase $ Network.socketToHandle socket IO.ReadWriteMode)
            (\handle -> liftBase $ IO.hClose handle)
            (\handle -> do
               mvar <- newMVar False
               bracket (fork $ do
                          threadDelay 5000000
                          _ <- swapMVar mvar True
                          return ())
                       (killThread)
                       (\_ -> runConnectionT handle (sourceHandle handle))
               takeMVar mvar)

ご覧のとおりProducer、プリミティブの観点から を作成しようとしていますwithConnectionForever。そのプリミティブのタイプは次のとおりです。

withConnectionForever
  :: (MonadBaseControl IO m, MonadLogger m)
  => NetworkSettings
  -> (Network.Socket -> m Bool)
  -> m ()

ご想像のとおり、コンパイル時にエラー メッセージが表示されます。それは:

Haskell/IRC.hs:128:54:
    Couldn't match expected type `ConnectionT m0 a0'
                with actual type `ConduitM i0 ByteString.ByteString m1 ()'
    In the return type of a call of `sourceHandle'
    In the second argument of `runConnectionT', namely
      `(sourceHandle handle)'
    In the expression: runConnectionT handle (sourceHandle handle)

さて、私は への呼び出しの型が明らかにコンジットではないことを知っていますが、コンジットもモナドであり、ハードコーディングされたモナドの代わりに自由なモナドwithConnectionForeverを使用するという事実のおかげで、なんとかコンジットになることを望んでいました。withConnectionForever1。メッセージが何を伝えようとしているのかについての私の理解は、それが起こっていないということです。その理由と、それに対して私ができることを知りたい.

完全を期すために、プリミティブのソースを次に示します。

withConnectionForever
  :: (MonadBaseControl IO m, MonadLogger m)
  => NetworkSettings
  -> (Network.Socket -> m Bool)
  -> m ()
withConnectionForever networkSettings action = do
  let loop nFailures = do
        maybeSocket <- newConnection networkSettings
        case maybeSocket of
          Nothing -> return ()
          Just socket -> do
            terminatedNormally <- action socket
            if terminatedNormally
              then loop 0
              else do
                exponentTwiddle <- liftBase $ Random.randomRIO (0, 100)
                let exponent =
                      1.25 + fromIntegral (exponentTwiddle - 50) / 100.0
                    delay = floor $ 1000000.0 *
                      ((0.5 ** (fromIntegral nFailures * negate exponent))
                       - 1.0 :: Double)
                $(logInfo) (Text.concat
                  ["Abnormal disconnection from the network ",
                   networkSettingsName networkSettings,
                   "; pausing attempts for ",
                   Text.pack $ show $ fromIntegral delay / 1000000.0,
                   " seconds..."])
                liftBase $ threadDelay delay
                loop (nFailures + 1)
  loop 0

侵襲性を最小限に抑えた方法で実行できる場合を除き、プリミティブを書き直さないことを本当に望んでいますが、それはテーブルにあると思います。

前もって感謝します!

4

1 に答える 1

1

関連することは

(\_ -> transPipe (runConnectionT handle) (sourceHandle handle))

それ以外の

(\_ -> runConnectionT handle (sourceHandle handle))

御時間ありがとうございます!:D

于 2013-10-27T23:59:04.530 に答える