我正在尝试学习 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)
这是第二个版本。
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)
对于相同的参数,它们都给出相同的输出。但在第一个版本中,为了检查列表的长度(顺便说一下,这是状态),我引用列表 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)
您返回从 get
获得的列表,而不是您放入
到状态中的列表,因此您生成的伪随机数比rnds1
(然后您将忽略它),但返回相同的列表。
关于haskell - 这两个非常相似的 haskell 状态计算有什么区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15206497/