У меня возникли трудности с попыткой выяснить, почему следующие два, казалось бы, эквивалентные определения бесконечной последовательности случайных чисел (inf
и inf'
) оцениваются совершенно по-разному :Бесконечные циклы случайной последовательности с randomIO, но не с getRandom
import Control.Monad.Random (Rand, evalRandIO, getRandom)
import System.Random (Random, RandomGen, randomIO)
inf :: (RandomGen g, Random a) => Rand g [a]
inf = sequence (repeat getRandom)
inf' :: (Random a) => IO [a]
inf' = sequence (repeat randomIO)
-- OK
main = do
i <- evalRandIO inf
putStrLn $ show $ take 5 (i :: [Int])
-- HANGS
main' = do
i <- inf'
putStrLn $ show $ take 5 (i :: [Int])
при вызове main'
завершаясь и печатает 5 случайных чисел, в то время как main
петель бесконечно - то, что вызывает sequence . repeat
быть оценены по-разному на getRandom
, чем на randomIO
?
Вы имеете в виду, что 'main' завершается и' main'' висит? –
@ AndrásKovács да, точно. –
Существует важное различие между ними. 'evalRandIO' использует' IO' для получения начального генератора, генерируя бесконечный список из этого, не требует больше ввода-вывода. 'randomIO' требует вызова' IO' для каждого случайного числа, поэтому он зависает, когда он пытается вернуться в бесконечный список (если вы не используете 'unsaveInterleaveIO'). – cchalmers