查看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
始终返回相同的输出?
答案 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;更新全局生成器。因此,每次调用都会更新全局生成器。