haskell - 这两个非常相似的 haskell 状态计算有什么区别

标签 haskell state

我正在尝试学习 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/

相关文章:

haskell - 如何在运行时设置线程数(避免+RTS -N#)

haskell - 如何将 Pandoc Inline 数据类型转换为 Blaze HTML 数据类型

haskell - 字符串变量作为 haskell 命令

angularjs - 为什么这个工厂返回一个 $$state 对象而不是 response.data?

arrays - 面向新手的 STArray 文档和状态/ST 相关问题

javascript - 异步等待到actionCreator,我应该返回结果吗?

java - 如何将这个简单的 OOP 程序转换为函数式编程语言?

haskell - 如何在不与 Haskell 中的类型系统发生冲突的情况下对 monad 进行抽象?

javascript - React JS Dropdown onchange 功能不起作用。尝试了几种方法都没有成功

asp.net - IIS Web场的防弹 session