次のプログラムは正しく終了します。
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
私が探していたものです。
EDIT2: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
。IOモナドでランダムリストを非常に簡単に生成し、必要に応じてそれを純粋関数に渡すことができると非常に便利です。これが標準ライブラリに含まれてはならない理由がわかりません。