我可能只花了一天的计算时间徒劳:)
问题在于我(天真)将大约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
我试过......但它只会消耗更多内存,直到它被操作系统杀死。
答案 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。