Как связать, положить и вернуть взаимодействовать здесь?

Учитывая следующий код

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 не должны зависеть от предыдущих результатов.

1 ответ

Когда я тестирую обе функции с одинаковым начальным состоянием, я получаю один и тот же ответ:

λ> 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
Другие вопросы по тегам