这两个非常相似的haskell状态计算之间的区别是什么

Jay*_*Jay 3 state haskell

我正在努力学习haskell State monad.所以我写了一个函数来使用State monad生成一个随机数列表.

这是第一个版本.

rnds :: Int -> [Int]
rnds n = evalState (help (mkStdGen 007)) []
  where help prng = do s <- get
            let (a, nprng) = randomR (1,6) prng                                 
            put (a:s)
            if length s == n then (return s)
                             else (help nprng)
Run Code Online (Sandbox Code Playgroud)

这是第二个版本.

rnds1 :: Int -> [Int]
rnds1 n = evalState (help (mkStdGen 007)) []
  where help prng = do s <- get
            let (a, nprng) = randomR (1,6) prng                                 
            put (a:s)
            ns <- get
            if length ns == n then (return ns)
                              else (help nprng)
Run Code Online (Sandbox Code Playgroud)

对于相同的参数,它们都给出相同的输出.但是在第一个版本中,为了检查列表的长度(顺便说一下是状态),我引用了列表s.但是s在我做之前获得了put (a:s).因此,当我检查长度时,我认为它会在我做之前给出's'的长度put (a:s).但它似乎并非如此,因为如果给出相同的参数,则第一个版本的输出与第二个版本的输出相同.

第二个版本对我来说更容易理解.在检查列表的长度之前ns,我首先要做的ns <- get是获得新的更新状态.

有人可以告诉我发生了什么事吗?我感觉我严重误解了Haskell的工作方式或者关于State monad本身的一些事情.

感谢致敬.

Dan*_*her 5

rnds,

put (a:s)
if length s == n then (return s)
Run Code Online (Sandbox Code Playgroud)

你返回从你获得的列表get,而不是你put进入状态的列表,所以你生成一个比一个伪随机数rnds1(然后你忽略),但返回相同的列表.