我浏览了一些关于 State monad 的教程,我想我明白了。
例如,在这个不错的教程中:
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
好的,所以我可以使用 getRandom:
*Main> runState getRandom 0
(0,12345)
*Main> runState getRandom 0
(0,12345)
*Main> runState getRandom 1
(16838,1103527590)
但是我每次调用它时仍然需要将种子传递给 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 monad,因为我在大多数教程中看到的似乎不是“持久”状态,而只是一种方便的线程状态方式。
那么......我怎样才能拥有自动初始化的状态(可能来自使用时间和其他不可预测数据的某些函数),就像 Random 模块一样?
非常感谢!