Мой контекст — биоинформатика, в частности секвенирование следующего поколения, но проблема общая, поэтому я буду использовать файл журнала в качестве примера.
] Файл очень большой (гигабайты большие, сжатые, поэтому он не помещается в памяти), но его легко разобрать (каждая строка является записью), поэтому мы можем легко написать что-то вроде:
parse :: Lazy.ByteString -> [LogEntry]
Теперь у меня есть много статистических данных, которые я хотел бы вычислить из файла журнала. Проще всего написать отдельные функции, такие как:
totalEntries = length
nrBots = sum . map fromEnum . map isBotEntry
averageTimeOfDay = histogram . map extractHour
Все они имеют вид foldl' kz .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-ячейки может быть сборщиком мусора. Если я вычисляю только одну статистику, вот что происходит.
Я могу написать одну большую функцию, которая делает это, но это не компонуемый код.
Альтернатива ly, что я и делал, я запускаю каждый проход отдельно, но это каждый раз перезагружает и распаковывает файл.