Как здесь взаимодействуют bind, put и return?

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

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


person Hernan Di Giorgi    schedule 11.07.2013    source источник
comment
Ваш вопрос в том виде, в котором он был опубликован, трудно понять. Я не уверен, что вы спрашиваете. Кстати, вашу rollDie функцию можно переписать rollDie = state (randomR (1,6))   -  person cdk    schedule 11.07.2013
comment
Где определяется GeneratorState? Кроме того, как вы тестировали эти функции?   -  person mhwombat    schedule 11.07.2013
comment
Кажется, я нашел ваш GeneratorState здесь: en.wikibooks.org/wiki/Haskell/Understanding_monads/ Состояние   -  person mhwombat    schedule 11.07.2013
comment
Мой главный вопрос был о том, какая разница, использовать или не использовать новый генератор››. Я пишу две функции только для того, чтобы показать свою интерпретацию нотации do.   -  person Hernan Di Giorgi    schedule 11.07.2013


Ответы (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
person mhwombat    schedule 11.07.2013