Обоснование лени

У меня есть следующий фрагмент:

import qualified Data.Vector as V
import qualified Data.ByteString.Lazy as BL
import System.Environment
import Data.Word
import qualified Data.List.Stream as S

histogram ::  [Word8] -> V.Vector Int
histogram c = V.accum (+) (V.replicate 256 0) $ S.zip (map fromIntegral c) (S.repeat 1)

mkHistogram file = do
  hist <- (histogram . BL.unpack) `fmap` BL.readFile file
  print hist

Я вижу это так: Ничего не делается до печати. При печати thunks разворачиваются сначала распаковкой, а затем отображением из Integral по одному Word8 за раз. Каждое из этих word8 заархивировано с 1, опять же по одному значению за раз. Эти кортежи затем принимаются функцией накопителя, которая обновляет массив, по одному кортежу / Word8 за раз. Затем мы переходим к следующему преобразователю и повторяем его до тех пор, пока не кончится содержимое.

Это позволит создавать гистограммы в постоянной памяти, но, увы, этого не происходит, а вместо этого происходит сбой с переполнением стека. Если я попытаюсь профилировать его, я вижу, что он работает до конца, но занимает много памяти (300-500 МБ для файла размером 2,5 МБ). Память получается линейно до конца, пока ее не освободят, образуя «красивый» треугольный граф.

Где мои рассуждения пошли не так, и какие шаги я должен предпринять, чтобы запустить этот запуск в постоянной памяти?

12
задан Masse 11 March 2011 в 15:16
поделиться