私の文脈はバイオインフォマティクス、特に次世代シーケンシングですが、問題は一般的です。例としてログファイルを使用します。
ファイルは非常に大きい(ギガバイトの大きさで、圧縮されているため、メモリに収まりません)が、解析が簡単であるため(各行はエントリです)、次のように簡単に記述できます。
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セルをガベージコレクションできるように、フォールドを同期的に実行する必要があります。統計を1つだけ計算すると、これが起こります。
これを行う大きな関数を1つ書くことはできますが、それは構成不可能なコードです。
または、これまで行ってきたことですが、各パスを個別に実行しますが、これにより、毎回ファイルが再ロードおよび解凍されます。