随机数和getStdGen

时间:2014-12-28 08:32:16

标签: haskell monads

从Haskell wikibook我们有:

import Control.Monad
import Control.Monad.Trans.State
import System.Random

type GeneratorState = State StdGen

rollDie :: GeneratorState Int
rollDie = do
  generator <- get
  let (value, newGenerator) = randomR (1,6) generator
  put newGenerator
  return value

如果我们执行:

evalState rollDie (mkStdGen 0)

然后我们得到一个返回类型的Int。

我理解这一点,但我想知道是否有可能将函数getStdGen访问的系统生成器用于此逻辑。 getStdGen函数在IO monad中运行,我的问题是(当然这必须是最常见的Haskell问题)如何从IO上下文中获取生成器以用于上面的非IO monad代码?

为新手问题道歉。我知道不应该使用unsafePerformIO,否则会感到困惑。

1 个答案:

答案 0 :(得分:1)

问题的核心是不可能凭空产生随机数。您可以使用某些输入为生成器设置种子(这是您使用mkStdGen 0执行的操作),或者您可以使用getStdGen获取系统。

mkStdGen 0的问题在于它是一个常数,所以你的随机数流也会通过常量非常清楚地显示其伪随机性。

getStdGen的问题在于它在IO monad中。

你不能让IO中的发生器用于纯计算,这就是使IO成为monad的重点。但是在IO中,您可以使用常规的注释来绑定它:

main = do
  gen <- getStrGen
  print $ evalState rollDie gen

当然,它只会产生一次独特的结果。

我衷心同意the comment recommending MonadRandom。我一直在使用它进行基于随机的计算,因为我发现了它,并没有回头。