Следующая программа корректно завершается:
import System.Random
randomList = mapM (\_->getStdRandom (randomR (0, 50000::Int))) [0..5000]
main = do
randomInts <- randomList
print $ take 5 randomInts
Продолжительность:
$ runhaskell test.hs
[26156,7258,29057,40002,26339]
Однако, заполняя его бесконечным списком, программа никогда не завершается, и при компиляции в конечном итоге выдает ошибку переполнения стека!
import System.Random
randomList = mapM (\_->getStdRandom (randomR (0, 50000::Int))) [0..]
main = do
randomInts <- randomList
print $ take 5 randomInts
Запуск
$ ./test
Stack space overflow: current size 8388608 bytes.
Use `+RTS -Ksize -RTS' to increase it.
Я ожидал, что программа будет лениво оценивать getStdRandom
каждый раз, когда я выбираю элемент из списка, заканчивая после этого 5 раз. Почему он пытается оценить весь список?
Спасибо.
Есть ли лучший способ получить бесконечный список случайных чисел? Я хочу передать этот список в чистую функцию.
РЕДАКТИРОВАТЬ: Еще несколько чтения показали, что функция
randomList r = do g <- getStdGen
return $ randomRs r g
это то, что я искал.
РЕДАКТИРОВАТЬ 2: после прочтения ответа Camccann я понял, что getStdGen
получает новое семя при каждом вызове. Вместо этого лучше использовать эту функцию в качестве простого генератора случайных списков из одного кадра:
import System.Random
randomList :: Random a => a -> a -> IO [a]
randomList r g = do s <- newStdGen
return $ randomRs (r,g) s
main = do r <- randomList 0 (50::Int)
print $ take 5 r
Но я до сих пор не понимаю, почему мой mapM
звонок не завершился. Очевидно, это не связано со случайными числами, но может быть связано с mapM
, может быть.
Например, я обнаружил, что следующее также не заканчивается:
randomList = mapM (\_->return 0) [0..]
main = do
randomInts <- randomList
print $ take 50000 randomInts
Что дает? Кстати, ИМХО, вышеупомянутая randomInts
функция должна быть в System.Random
. Очень удобно иметь возможность просто генерировать случайный список в монаде ввода-вывода и передавать его в чистую функцию при необходимости, я не понимаю, почему этого не должно быть в стандартной библиотеке.