Я изучаю Haskell и в настоящее время пытаюсь склонить голову к монадам. Во время игры с некоторым генерированием случайных чисел я снова сработал на ленивой оценке. Чтобы упростить что-то близкое к:
roll :: State StdGen Int
roll = do
gen <- get
let (n, newGen) = randomR (0,1) gen
put newGen
return n
main = do
gen <- getStdGen
let x = sum $ evalState (replicateM iterations roll) gen
print x
в нечто подобное:
roll' :: IO Int
roll' = getStdRandom $ randomR (0,1)
main = do
x' <- fmap sum $ replicateM iterations roll'
print x'
на большее число iterations
, скажем, 1000 * 1000 * 10
, второй пример приводит к переполнению стека.
Почему первая версия с удовольствием работает в постоянном пространстве, а вторая взрывается?
Говоря более широко, вы можете рекомендовать некоторые чтения, чтобы улучшить одну ментальную модель ленивой оценки Хаскелла? (Вводный для промежуточного уровня, желательно.) Поскольку, когда дело доходит до оценки в Haskell, моя интуиция полностью меня терпит.