Мой контекст - это биоинформатика, в частности, последовательность следующего поколения, но проблема является общей; поэтому я буду использовать файл журнала в качестве примера.
Файл очень большой (Gigabytes большой, сжатый, поэтому он не поместится в памяти), но легко разобрать (каждая строка является записью), поэтому мы можем легко написать что-то вроде:
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 могут быть собраны в мусор. Если я вычисляю только одну статистику, это то, что происходит.
Я могу написать одну большую функцию, которая делает это, но это неконсолидируемый код.
В качестве альтернативы, это то, что я делал, я запускаю каждый проход отдельно, но каждый раз перезагружает и распаковывает файл.