2014-05-17 14 views
9

Thư viện Pipes.Aeson cho thấy nhiều chức năng sau:Truyền phân tích cú pháp của JSON trong Haskell với Pipes.Aeson

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

Nếu tôi sử dụng evalStateT với phân tích cú pháp này và một tập tin xử lý như một cuộc tranh cãi, một đối tượng JSON duy nhất là đọc từ tệp và phân tích cú pháp.

Sự cố là tệp chứa một số đối tượng (tất cả cùng loại) và tôi muốn gấp hoặc giảm chúng khi chúng được đọc.

Pipes.Parse cung cấp:

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

nhưng như bạn có thể thấy điều này trả về một phân tích cú pháp mới - Tôi không thể nghĩ ra một cách để cung cấp các phân tích cú pháp đầu tiên là một cuộc tranh cãi.

Dường như một trình phân tích cú pháp thực sự là một Nhà sản xuất trong một biến áp đơn vị StateT. Tôi tự hỏi liệu có cách nào để giải nén Nhà sản xuất khỏi StateT để evalStateT có thể được áp dụng cho foldAll Parser hay không, và nhà sản xuất từ ​​bộ giải mã phân tích cú pháp.

Đây có lẽ là cách tiếp cận sai hoàn toàn.

Câu hỏi của tôi, viết tắt:
Khi phân tích cú pháp tệp bằng Pipes.Aeson, cách tốt nhất để gấp tất cả các đối tượng trong tệp là gì?

Trả lời

4

Thay vì sử dụng decode, bạn có thể sử dụng decodedparsing lens từ Pipes.Aeson.Unchecked. Nó biến nhà sản xuất của ByteString thành nhà sản xuất các giá trị JSON được phân tích cú pháp.

{-# 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 

Giá trị trả về của intProducer là một chút đáng sợ, nhưng nó chỉ có nghĩa là intProducer kết thúc hoặc với một lỗi phân tích cú pháp và các byte chưa phân tích sau khi lỗi, hoặc với giá trị trả về của nhà sản xuất gốc (đó là () trong trường hợp của chúng ta).

Chúng ta có thể bỏ qua các giá trị trả về:

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

Và cắm sản xuất thành một fold từ Pipes.Prelude, như sum:

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

Trong ghci:

λ :main 
10 

Cũng lưu ý rằng các chức năng purelyimpurely cho phép bạn áp dụng cho các nếp gấp của nhà sản xuất được xác định trong gói foldl.

+2

Bạn cũng có thể thực hiện 'zoom decoded (foldAll step begin done)' –

+0

@GabrielGonzalez Ah vâng, tôi quên một người cũng có thể sử dụng 'zoom' để áp dụng ống kính cho 'Parser'. – danidiaz

+0

@GabrielGonzalez Ngoài ra, có vẻ như sử dụng 'zoom decoded ...' làm cho các lỗi phân tích cú pháp dễ xử lý hơn. – danidiaz

Các vấn đề liên quan