【发布时间】:2014-12-28 08:32:16
【问题描述】:
来自我们拥有的 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,否则会感到困惑。
【问题讨论】:
-
您想要的可能是
MonadRandom类(在Control.Monad.Random中)。如果你写了一个MonadRandom m => m Int类型的函数,那么你可以用IO Int来实例化它,这将使用getStdGen,或者Rand Int(Rand是一个特殊的monad,用于生成随机数,本质上和State StdGen一样) ,您可以照常使用。然而,最简单的解决方案是evalState rollDie `fmap` getStdGen,它只是将函数evalState rollDie应用于getStdGen创建的StdGen。 -
这个关于随机数的问题完全是关于 IO 以及如何使用绑定?