9

Pipes.Aeson ライブラリは、次の関数を公開します。

decode :: (Monad m, ToJSON a) => Parser ByteString m (Either DecodingError a)

このパーサーとファイル ハンドルを引数として evalStateT を使用すると、1 つの JSON オブジェクトがファイルから読み取られて解析されます。

問題は、ファイルに複数のオブジェクト (すべて同じタイプ) が含まれており、それらを読み取るときに折りたたむか縮小したいことです。

Pipes.Parse は以下を提供します。

foldAll :: Monad m => (x -> a -> x) -> x -> (x -> b) -> Parser a m b

しかし、ご覧のとおり、これは新しいパーサーを返します。最初のパーサーを引数として指定する方法が思い浮かびません。

パーサーは実際には StateT モナド変換子のプロデューサーのようです。StateT からプロデューサーを抽出して、evalStateT を foldAll パーサーに適用し、プロデューサーをデコード パーサーから抽出する方法はないかと考えました。

ただし、これはおそらく完全に間違ったアプローチです。

簡単に言えば、私の質問:
Pipes.Aeson を使用してファイルを解析する場合、ファイル内のすべてのオブジェクトを折りたたむ最良の方法は何ですか?

4

1 に答える 1

5

を使用する代わりに、 の解析レンズdecode使用できます。のプロデューサーを、解析された JSON 値のプロデューサーに変えます。decoded Pipes.Aeson.UncheckedByteString

{-# LANGUAGE OverloadedStrings #-}

module Main where

import Pipes
import qualified Pipes.Prelude as P
import qualified Pipes.Aeson as A
import qualified Pipes.Aeson.Unchecked as AU
import qualified Data.ByteString as B

import Control.Lens (view)

byteProducer :: Monad m => Producer B.ByteString m ()
byteProducer = yield "1 2 3 4"

intProducer :: Monad m => Producer Int m (Either (A.DecodingError, Producer B.ByteString m ()) ())
intProducer = view AU.decoded byteProducer

の戻り値intProducerは少し怖いですが、これは がintProducer解析エラーとエラー後の未解析バイト、または元のプロデューサーの戻り値 (この()場合) で終了することを意味するだけです。

戻り値は無視できます。

intProducer' :: Monad m => Producer Int m ()
intProducer' = intProducer >> return ()

そして、次のように、プロデューサーをからのフォールドに接続します。Pipes.Preludesum

main :: IO ()
main = do
    total <- P.sum intProducer'
    putStrLn $ show total

ghci で:

λ :main
10

また、これらの関数を使用すると、foldlパッケージで定義されたプロデューサーの折り畳みに純粋に適用できることにも注意してください。

于 2014-05-17T19:54:58.890 に答える