Haskell: Могу ли я выполнить несколько сверток одного и того же ленивого списка, не сохраняя список в памяти?

Мой контекст — биоинформатика, в частности секвенирование следующего поколения, но проблема общая, поэтому я буду использовать файл журнала в качестве примера.

] Файл очень большой (гигабайты большие, сжатые, поэтому он не помещается в памяти), но его легко разобрать (каждая строка является записью), поэтому мы можем легко написать что-то вроде:

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, что я и делал, я запускаю каждый проход отдельно, но это каждый раз перезагружает и распаковывает файл.

19
задан Don Stewart 29 May 2012 в 17:17
поделиться