0

type の Conduit と typeConduit a m aの function があり(a -> Maybe a)ます。関数を実行して、Nothing が返された場合は、Conduit を使用します。つまり、タイプの関数が必要です

maybePipe :: Conduit a m b -> (a -> Maybe b) -> Conduit a m b

または、より制限されたタイプの

maybePipe :: Conduit a m a -> (a -> Maybe a) -> Conduit a m a

それが役立つ場合、私の特定のケースは次のとおりです。

IRC メッセージを処理するコードを書いており、関数があります。

runClient :: Conduit IRC.Message IO IRC.Message -> ClientSettings -> IO ()
runClient pipe address = runTCPClient' pipe' address where
    pipe' = mapC IRC.decode $= concatMapC id $= pipe $= mapC IRC.encode $= mapC (++ "\r\n")
    handlePings (IRC.Message (Just (IRC.Server serverName)) "PING" []) = Just $ IRC.pong serverName
    handlePings (IRC.Message Nothing "PING" [server]) = Just $ IRC.pong server
    handlePings (IRC.Message Nothing "PING" []) = Just $ IRC.pong (getHost address)
    handlePings _ = Nothing
    runTCPClient' :: Conduit ByteString IO ByteString -> ClientSettings -> IO ()
    runTCPClient' pipe address = runTCPClient address runClient where
        runClient appdata = appSource appdata $= linesUnboundedAsciiC $= pipe $$ appSink appdata

その関数で (または同等の)ことができるようにしたいmaybePipe handlePings pipeので、IRC メッセージが ping の場合、pong で応答し、ユーザー指定の Conduit を呼び出しません。

4

2 に答える 2

2

Hoogle を検索すると、ほとんど同じ型シグネチャを持つ関数mapOutputMaybeが見つかります。しかし、より慣用的な方法は、と融合することData.Conduit.List.mapMaybeです。

編集

スクラッチ、私はあなたが今求めていることを理解しています. いいえ、組み込みのコンビネータはありません。しかし、それを構築するのは簡単です:

myHelper onNothing f = awaitForever $ maybe onNothing yield . f
于 2014-06-05T02:59:27.113 に答える
0

Michael のコンビネータを使用する(a -> Maybe b)と、最初のアイテムで acress が呼び出されるだけで、onNothingパイプが引き継がれます。これは私が探していたものではありませんでした。

代わりに、ZipConduit私の特定の例で(を使用してconduit-combinators):

pingHandlingPipe = 
  getZipConduit $ ZipConduit (concatMapC handlePings) 
               *> ZipConduit (takeWhileC (not.isJust.handlePings) $= pipe)

または、一般化された

pipeMaybe maybeF pipe = 
  getZipConduit $ ZipConduit (concatMapC maybeF)
               *> ZipConduit (takeWhileC (not.isJust.maybeF) $= pipe)

残念ながら、これは(a -> Maybe b)関数を 2 回呼び出します。

于 2014-06-05T06:39:57.900 に答える