我的背景是生物信息学,尤其是下一代测序,但问题是通用的;所以我将以一个日志文件为例。
该文件非常大(千兆字节大,已压缩,因此无法放入内存),但易于解析(每一行都是一个条目),因此我们可以轻松编写如下内容:
parse :: Lazy.ByteString -> [LogEntry]
现在,我想从日志文件中计算出很多统计数据。编写单独的函数是最简单的,例如:
totalEntries = length
nrBots = sum . map fromEnum . map isBotEntry
averageTimeOfDay = histogram . map extractHour
所有这些都是形式foldl' k z . map f
。
问题是,如果我尝试以最自然的方式使用它们,比如
main = do
input <- Lazy.readFile "input.txt"
let logEntries = parse input
totalEntries' = totalEntries logEntries
nrBots' = nrBots logEntries
avgTOD = averageTimeOfDay logEntries
print totalEntries'
print nrBots'
print avgTOD
这将在内存中分配整个列表,这不是我想要的。我希望折叠同步完成,以便可以对 cons 单元进行垃圾收集。如果我只计算一个统计数据,就会发生这种情况。
我可以编写一个大函数来执行此操作,但它是不可组合的代码。
或者,这就是我一直在做的,我分别运行每个通道,但这每次都会重新加载和解压缩文件。