2014-05-17 80 views
9

的Pipes.Aeson庫公開以下功能:流解析在Haskell與Pipes.Aeson

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

如果我使用evalStateT這個解析器和一個文件句柄作爲一個參數,一個JSON對象從文件中讀取並解析。

問題是該文件包含幾個對象(所有相同的類型),我想摺疊或減少他們閱讀。

Pipes.Parse規定:

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

但你可以看到它返回一個新的解析器 - 我想不出作爲參數提供第一解析器的一種方式。

它看起來像一個解析器實際上是一個StateT monad變換器中的生產者。我想知道是否有辦法從StateT中提取Producer,這樣evalStateT就可以應用到foldAll解析器和解碼器解析器中的Producer。

雖然這可能是完全錯誤的方法。

我的問題,簡而言之:
使用Pipes.Aeson解析文件時,摺疊文件中所有對象的最佳方法是什麼?

回答

4

代替使用decode,您可以使用decodedparsing lensPipes.Aeson.Unchecked。它將ByteString的生產者變成解析的JSON值的生產者。

{-# 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.Prelude堵塞製作成fold,像sum

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

在ghci的:

λ :main 
10 

還要注意即功能purelyimpurely允許您應用foldl包中定義的生產者摺疊。

+2

你也可以做'zoom解碼(foldAll步驟開始完成)' –

+0

@GabrielGonzalez啊是的,我忘了也可以用'zoom'將鏡頭應用到'Parser's。 – danidiaz

+0

@GabrielGonzalez另外,似乎使用'zoom decoding ...'會使解析錯誤更容易處理。 – danidiaz