了解RandomGen#next

时间:2014-06-22 02:52:41

标签: haskell

查看RandomGen#next,文档说:

next :: g -> (Int, g)

The next operation returns an Int that is uniformly distributed in the range 
returned by genRange (including both end points), and a new generator.

在REPL中使用它,我希望x next打印出相同的数字。

ghci> let x = getStdRandom
ghci> x next
169285648
ghci> x next
473378030
ghci> x next
896978399

为什么没有x next引用透明,即调用x next始终返回相同的输出?

2 个答案:

答案 0 :(得分:6)

查看getStdRandom

的定义
getStdRandom :: (StdGen -> (a,StdGen)) -> IO a
getStdRandom f = atomicModifyIORef theStdGen (swap . f)

换句话说,它做了类似的事情(但是原子地):

getStdRandom f = do
    gen <- getStdGen
    let (result, gen') = f gen
    setStdGen gen'
    return result

因此,它获取随机数生成器,运行您的函数,然后将新的随机数生成器放在适当的位置。当您运行getStdRandom next几次时,它将在开始时检索随机数生成器,对随机数生成器进行线程化,使得每个下一个生成器从最后一个接收新的随机数生成器。这意味着next的每次调用都会收到一个不同的随机数生成器。

但如果getStdRandom next的类型为Int,怎么会发生这种情况?诀窍是,它不是。它的类型为IO Int,GHCi将自动执行并显示结果值,就好像它是Int一样。

如果你想从环境中获取一个随机数生成器并多次使用它,你应该得到它一次(而不是通过你的函数得到一个将RNG状态线程化的函数并返回另一个IO)和然后使用:

ghci> x <- getStdGen
ghci> next x
(803259519,803300211 40692)
ghci> next x
(803259519,803300211 40692)
ghci> next x
(803259519,803300211 40692)

答案 1 :(得分:0)

要了解这里发生了什么,您需要检查getStdRandom的类型签名。

> :t getStdRandom
getStdRandom :: (StdGen -> (a, StdGen)) -> IO a

getStdRandom返回IO a,因此返回相同值并使用相同的输入不一定在桌面上。

getStdRandom的文档说明它从当前的全局随机生成器获取值,并使用新生成器&#34;更新全局生成器。因此,每次调用都会更新全局生成器。

相关问题