gpt4 book ai didi

haskell - 为什么我的 haskell 程序内存不足?

转载 作者:行者123 更新时间:2023-12-01 07:20:56 27 4
gpt4 key购买 nike

各位编码员你好。
所以我决定重写一些我在haskell中闲逛的旧脚本,只是因为我需要练习并且我喜欢这种语言。所以在这里我试图过滤一个巨大的文件(大约 1.7 GB),剪切不感兴趣的行并将剩余的内容写入另一个文件中。

我认为 haskell 的懒惰性质将是理想的选择,但代码很快就会耗尽内存。以前的版本(c# 或 Python)有一个读行 -> 写行方法,但我在这里尝试了不同的方法。我应该重写代码以反射(reflect)以前的版本还是我遗漏了什么。

所以这是负责原始文件过滤的功能:

getLines :: FilePath -> IO [[String]]
getLines path = do
text<-readFile path
let linii=lines text
let tokens = map words linii
let filtrate=[x|x<-tokens,length x>7,isTimeStamp (x!!0),isDiagFrame x]
return filtrate

这个负责在新文件中一次写入一行(尽管我尝试直接使用 writeFile 并且失败了:):
writeLines ::Handle->[[String]]->IO ()
writeLines handle linii = do
let linie=concat $ intersperse " " (head linii)
hPutStrLn handle linie
if length linii > 0 then
writeLines handle (tail linii)
else
print "Writing complete..."

这两个是主要功能,另一个负责获取句柄并传递它:
writeTheFile :: FilePath->FilePath->IO ()
writeTheFile inf outf = do
handle<-openFile outf WriteMode
linii<-getLines inf
writeLines handle linii
print "Write Complete"


main = do
arg<-getArgs
if length arg/=2 then
print "Use like this : trace_pars [In_File] [Out_File] !"
else
writeTheFile (arg!!0) (arg!!1)

任何建议将不胜感激...提前致谢

最佳答案

这里的问题是在这一行:

                    if length linii > 0     then

您正在计算行列表的长度。这意味着必须加载整个行列表才能对其进行计数。这意味着您正在阅读的整个文件需要加载到内存中。不好!

解决方法是使用 if not . null $ linii then反而。 null函数检查列表是否为空(仅强制加载列表的第一行),以及 not表现得像你期望的那样。

如果您想要更惯用的版本 writeLines (注意使用 FilePath 而不是 Handle ):
writeLines :: FilePath -> [[String]] -> IO ()
writeLines filename = writeFile filename . unlines . map unwords

此功能与:
writeLines filename lines =
writeFile filename mergedFile
where
mergedFile = unlines mergedLines
mergedLines = map unwords lines
unlinesintercalate "\n" 相同, 和 unwordsintercalate " " 相同. intercalate xconcat . intersperse x 相同.

我认为这应该足以让您了解正在发生的事情。

关于haskell - 为什么我的 haskell 程序内存不足?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9190712/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com