我正在努力学习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本身的一些事情.
感谢致敬.
在rnds,
put (a:s)
if length s == n then (return s)
Run Code Online (Sandbox Code Playgroud)
你返回从你获得的列表get,而不是你put进入状态的列表,所以你生成一个比一个伪随机数rnds1(然后你忽略),但返回相同的列表.