从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,否则会感到困惑。
答案 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。我一直在使用它进行基于随机的计算,因为我发现了它,并没有回头。