0

ネットワーク パケットの attoparsec パーサーの一部である以下のコードを単純化しようとしていますが、それを行うための適切な方法を見つけられません。

atEnd :: IO Bool解析するものが他にあるかどうかを判断するための への呼び出しから始まります。IO からアンラップしてから if ステートメントで使用するよりも適切な使用方法を見つけることはできませんがatEnd、モナド内で bool をチェックする簡単な方法が必要なようです。コードは次のとおりです。

maybePayload :: Parser (Maybe A.Value)
maybePayload = do
    e <- atEnd
    if e then return Nothing
    else do
        payload' <- char ':' *> takeByteString
        maybe mzero (return . Just) (maybeResult $ parse A.json payload') 

意図はNothing、ペイロードがない場合に戻りJust A.Value、有効な JSON ペイロードがある場合に戻り、無効なペイロードがある場合にパーサーが失敗することです。

最終的に作成される Packet レコードは次のとおりです。

data Packet = Packet
    { pID       :: Integer
    , pEndpoint :: String
    , pPayload  :: Maybe A.Value
    }
4

2 に答える 2

3

あなたはする必要のない多くの仕事をしています。まず、データの最後にいるかどうかを確認し、Nothingそれがうまくいかない場合は戻ります。最後にいると、コンテンツを必要とするパーサーが失敗し、使用maybeResultするとその失敗がNothing.

パーサーが失敗するのは、入力に文字 で始まらないデータが含まれている場合のみであり:、残りの場合は、それが を返すことによるものであっても成功しNothingます。

進行中の唯一の実際の解析は、 をチェックして:から使用することA.jsonです。プログラム全体を1つのパーサー内に記述しようとしていると思いますが、独自に解析を行い、必要に応じてそれを呼び出す必要があります。データの終わりをチェックしたり、コンテンツ全体を確実に取得したりする必要はありません。これらはすべてパーサーに無料で組み込まれています。不要なチェックをすべて取り除くと、

payload :: Parser A.Value
payload = char ':' *> A.json

必要に応じて、それを使用して、追加でラップされていないmaybeResult $ parse payload inputを取得できます。を適用しない場合は、返されたResultでパターン マッチを実行して、 ure、success、およびを個別に処理できます。Maybe A.ValueParsermaybeResultFailPartialSuccess


編集:OK、より明確になりました、ありがとう:

  • (コロンの後に無効な json が続く場合、失敗します)
  • コロンの後に有効な json が続く場合、成功し、それを Just でラップします
  • 入力の最後だけの場合は成功し、Nothing を返します

したがって、次のようになります。

maybePayload :: Parser (Maybe A.Value)
maybePayload = char ':' *> (Just <$> A.json)
            <|> (Nothing <$ endOfInput)

私は<$><$fromを使用しましたがControl.Applicative、必要に応じてfrom を使用しましたData.Functor

<$>は の中置バージョンでありfmap、すべての出力を でラップしJust <$> A.jsonます。A.jsonJust

<$fromをにfmap.const置き換えます。()endOfInputNothing

于 2012-12-04T23:22:47.890 に答える
0

パーサーモナドにはすでに組み込みの失敗の概念があるのに、なぜ Maybe で失敗をエンコードする必要があるのでしょうか? この方法で Maybe を使用する際の問題は、パーサーがバックトラックできないことです。

次のようなことを試して (私は型チェックを試みていません) option、呼び出し元で使用できます。

payload :: Parser Value
payload = do
  payload' <- char ':' *> takeByteString
  let res = parse A.json payload'
  case res of
    Error msg -> fail msg
    Success a -> return a
于 2012-12-04T22:19:09.803 に答える