如何在这里绑定、放置和返回交互



给定以下代码

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

我知道我可以把它翻译成:

rollDie2 :: GeneratorState Int
rollDie2 = get >>= generator ->let (value, newGenerator) = randomR(1,6) generator
                                in put newGenerator >> return value

我测试了使用和不使用put newGenerator >>的两个函数,它们产生了不同的结果。我的问题是为什么?put函数是纯函数,运算符(>>)表示return value不受先前结果的影响。

当我用相同的初始状态测试两个函数时,我得到了相同的答案:

λ> evalState rollDie (mkStdGen 0)
6
λ> evalState rollDie2 (mkStdGen 0)
6

我怀疑你在两次测试中都没有使用相同的状态。您究竟是如何测试这些功能的?

以下是状态(即随机数生成器)被修改的示例:

test :: GeneratorState (Int, Int)
test = do
  a <- rollDie -- modifies the state!
  b <- rollDie2 -- gets a different state
  return (a, b)
runTest :: IO ()
runTest = do
  g <- getStdGen
  let (a, b) = evalState test g
  print a
  print b

正如你所看到的,当你运行这个程序时,你会得到两个不同的答案。

λ> runTest
4
2

最新更新