私は State モナドに関するいくつかのチュートリアルを経て、アイデアを得たと思います。
たとえば、この素敵なチュートリアルのように:
import Data.Word
type LCGState = Word32
lcg :: LCGState -> (Integer, LCGState)
lcg s0 = (output, s1)
where s1 = 1103515245 * s0 + 12345
output = fromIntegral s1 * 2^16 `div` 2^32
getRandom :: State LCGState Integer
getRandom = get >>= \s0 -> let (x,s1) = lcg s0
in put s1 >> return x
OK、getRandom を使用できます。
*Main> runState getRandom 0
(0,12345)
*Main> runState getRandom 0
(0,12345)
*Main> runState getRandom 1
(16838,1103527590)
しかし、PRNG を呼び出すたびにシードを PRNG に渡す必要があります。Haskell 実装で利用可能な PRNG はそれを必要としないことを私は知っています:
Prelude> :module Random
Prelude Random> randomRIO (1,6 :: Int)
(...) -- GHC prints some stuff here
6
Prelude Random> randomRIO (1,6 :: Int)
1
ほとんどのチュートリアルで見られるのは「永続的な」状態ではなく、状態をスレッド化するための便利な方法であるように見えるため、おそらく State モナドを誤解していました。
それで... Random モジュールのように、自動的に初期化される状態 (時間やその他のあまり予測できないデータを使用する関数から可能) を取得するにはどうすればよいでしょうか?
どうもありがとう!