【发布时间】:2017-01-10 04:33:14
【问题描述】:
我想把给定目录下的所有json文件解析成数据类型Result。
所以我有一个解码功能
decodeResult :: Data.ByteString.Lazy.ByteString -> Maybe Result
我从 Data.Text.Lazy.IO 开始将文件加载到 Lazy ByteString,
import qualified Data.Text.Lazy.IO as T
import qualified Data.Text.Lazy.Encoding as T
getFileContent :: FilePath -> IO B.ByteString
getFileContent path = T.encodeUtf8 `fmap` T.readFile path
它编译了,但是我遇到了打开文件太多的问题,所以我想也许我应该使用withFile。
import System.IO
import qualified Data.ByteString.Lazy as B
import qualified Data.Text.Lazy.IO as T
import qualified Data.Text.Lazy.Encoding as T
getFileContent :: FilePath -> IO (Maybe Result)
getFileContent path = withFile path ReadMode $ \hnd -> do
content <- T.hGetContents hnd
return $ (decodeAnalytic . T.encodeUtf8) content
loadAllResults :: FilePath -> IO [Result]
loadAllResults path = do
paths <- listDirectory path
results <- sequence $ fmap getFileContent (fmap (path ++ ) $ filter (endswith ".json") paths)
return $ catMaybes results
在这个版本中,惰性 io 似乎从未被评估过,它总是返回空列表。但是如果我在 getFileContent 函数中打印内容,那么一切似乎都正常工作。
getFileContent :: FilePath -> IO (Maybe Result)
getFileContent path = withFile path ReadMode $ \hnd -> do
content <- T.hGetContents hnd
print content
return $ (decodeAnalytic . T.encodeUtf8) content
所以我不确定我错过了什么,我应该使用管道来处理这类事情吗?
【问题讨论】:
-
简单的答案是肯定的,使用导管之类的。更复杂的答案是,您的
loadAllResults是 难以置信 懒惰的 - 简单地执行loadAllResults x实际上并没有读取任何文件(或者实际上,打开它们)。当您尝试评估结果列表时,您会同时打开所有文件并尝试读取它们。withFile对你没有帮助,因为懒惰来自hGetContents- 尝试切换到非懒惰的文本 IO。
标签: json haskell io lazy-evaluation aeson