是否有办法懒散地“读”?

时间:2014-07-03 16:16:34

标签: haskell

我可能只花了一天的计算时间徒劳:)

问题在于我(天真)将大约3.5GB(压缩)[(Text, HashMap Text Int)]数据写入文件,此时我的程序崩溃了。当然,数据末尾没有最终],而且它的庞大规模使得手动编辑变得不可能。

数据是通过Prelude.show格式化的,此时我意识到Prelude.read在返回任何数据之前需要将整个数据集存入内存(不可能)。

现在......有没有办法恢复数据而无需手动编写解析器?

更新1

main = do
  s <- getContents
  let hs = read s :: [(String, M.Map String Integer)]
  print $ head hs

我试过......但它只会消耗更多内存,直到它被操作系统杀死。

3 个答案:

答案 0 :(得分:9)

排序。您仍将手动编写解析器...但它是一个非常简短且易于编写的解析器,因为几乎所有解析器都将发送到read。这个想法是这样的:read是严格的,但reads在处理单个元素时是懒惰的。因此,我们只需要去除reads在处理单个元素时不期望的位。这是一个让你入门的例子:

> let s = "[3,4,5," ++ undefined
> reads (drop 1 s) :: [(Int, String)]
[(3,",4,5,*** Exception: Prelude.undefined

我在最后添加了undefined作为证据,表明在列表头部生成解析后的String之前,它实际上并未读取整个3

答案 1 :(得分:7)

Daniels的答案可以扩展为使用此功能一次解析整个列表。然后,您可以按照您希望的方式直接访问它

lazyread :: Read a => [Char] -> [a]
lazyread xs = go (tail xs)
    where go xs = a : go (tail b)
        where (a,b) = head $ reads xs

答案 2 :(得分:1)

手动删除开头&#39; [&#39;。之后,您可以使用reads(注意s)逐步访问getContents。