imm*_*ate 9 parsing json haskell aeson haskell-pipes
Pipes.Aeson库公开以下函数:
decode :: (Monad m, ToJSON a) => Parser ByteString m (Either DecodingError a)
Run Code Online (Sandbox Code Playgroud)
如果我将evalStateT与此解析器和文件句柄作为参数一起使用,则会从文件中读取单个JSON对象并进行解析.
问题是文件包含几个对象(所有类型都相同),我想在阅读时折叠或缩小它们.
Pipes.Parse提供:
foldAll :: Monad m => (x -> a -> x) -> x -> (x -> b) -> Parser a m b
Run Code Online (Sandbox Code Playgroud)
但是你可以看到这会返回一个新的解析器 - 我想不出提供第一个解析器作为参数的方法.
看起来Parser实际上是StateT monad变换器中的Producer.我想知道是否有一种从StateT中提取Producer的方法,以便evalStateT可以应用于foldAll Parser,以及解码Parser中的Producer.
这可能完全是错误的方法.
我的问题,简而言之:
使用Pipes.Aeson解析文件时,折叠文件中所有对象的最佳方法是什么?
而不是使用的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
Run Code Online (Sandbox Code Playgroud)
返回值intProducer有点可怕,但它只表示intProducer在解析错误和错误后的未解析字节或原始生成器的返回值(()在我们的例子中)完成.
我们可以忽略返回值:
intProducer' :: Monad m => Producer Int m ()
intProducer' = intProducer >> return ()
Run Code Online (Sandbox Code Playgroud)
并将制作人插入折叠中Pipes.Prelude,例如sum:
main :: IO ()
main = do
total <- P.sum intProducer'
putStrLn $ show total
Run Code Online (Sandbox Code Playgroud)
在ghci:
? :main
10
Run Code Online (Sandbox Code Playgroud)
另请注意,这些函数纯粹且不可避免地允许您应用于foldl包中定义的生成器折叠.