【问题标题】:Haskell State example in wikibooks: fix per current Haskell?wikibooks 中的 Haskell 状态示例:按当前 Haskell 修复?
【发布时间】:2013-02-22 03:00:07
【问题描述】:

原来的问题

Haskell (> 7.4.2?) 的最新版本带有一个 mtl 包,它本身不再提供 State 构造函数,而是提供了一个 state 函数。

这弄乱了维基书籍页面中的 State 示例:http://en.wikibooks.org/wiki/Haskell/Understanding_monads/State

有人可以说明如何修改标题“介绍状态”之后的示例吗?这就是rollDie和rollDice的小函数。

页面前面有一个注释框,靠近标题“状态单子的定义”,它概括地描述了要做什么,但对我来说太模糊了。

另外,我不太清楚导入和包是如何工作的,因此对这个示例至关重要的一个可能相关的事情可能是指定需要哪些导入,因为它们也可能已经改变。

谢谢!

源代码

------- Adding code for ghci01.hs-------

-- http://en.wikibooks.org/wiki/Haskell/Understanding_monads/State
-- Introducing State heading and below

import Control.Monad
import System.Random

type GeneratorState = State StdGen

rollDie :: GeneratorState Int
rollDie = do generator <- get
             let (value, newGenerator) = randomR (1,6) generator
             put newGenerator
             return value

-- Test rollDie
-- evalState rollDie (mkStdGen 0)

rollDice :: GeneratorState (Int, Int)
rollDice = liftM2 (,) rollDie rollDie

-- Test rollDice
-- evalState rollDice (mkStdGen 666)

------- In GHCi --------
ghci> :l dice01.hs
[1 of 1] Compiling Main             ( dice01.hs, interpreted )
dice01.hs:7:23: Not in scope: type constructor or class `State'
dice01.hs:10:27: Not in scope: `get'
dice01.hs:12:14: Not in scope: `put'
Failed, modules loaded: none.

附录

对于在这里偶然发现的其他人:

这个问题的主题围绕着无效的示例代码,以及上面引用的 wikibooks 页面上的注释框中的警告。该框告诉 MTL 版本 > 2.0.0.0,由于 Control.Monad.State 的更改,某些示例代码将无法工作。

我的测试涉及 Haskell Platform 2012.4.0.0,其中包括 GHC 7.4.2,以及基于 mtl.cabal 文件的 MTL,我后来发现它是 1.1.1.1。 因此,注释的警告不应该适用,但示例代码仍然不起作用。此处答案推荐的更改(将导入 Control.Monad 更改为 Control.Monad.State)确实解决了问题。但很明显,这解决了与早期更改有关的问题,而不是注释中引用的 MTL 2.x。

此后我查看了 GHC 7.6.2 的源代码,但我根本找不到 MTL 库。相反,与状态相关的文件位于 library/transformers/Control/Monad/Trans/State 中。然后我走了一堆令人困惑的弯路,包括目前没有使用晚于 7.4.2 的 GHC 的 Haskell 平台的问题(即:没有 7.6.2)。

然后我找到了指向此 stackoverflow 问答的 MTL 文档 (http://www.haskell.org/haskellwiki/Monad_Transformer_Library):mtl, transformers, monads-fd, monadLib, and the paradox of choice ...至少在 2-3 年前,这解释了很多。

【问题讨论】:

  • 我认为这些功能适用于 MTL 版本 2.12(当前)。为什么你认为他们没有?您可以发布您在尝试它们时遇到的错误(以及您的完整代码)吗?
  • 我已经添加了我尝试过的代码,我认为它是从 wikibooks 页面逐字复制的。根据我指出的 Note 框,我很确定它不会起作用,并且错误消息(缺少 State 构造函数或类)与 Note 预测的一样。

标签: haskell state monads


【解决方案1】:

上面的代码只有一个问题

Control.Monad ===> Control.Monad.State

只有当你有类似的东西时,才会真正感受到变化

foo :: State Int Int
foo = State $ \a -> (a, a) -- This is an error

但修复它很容易:

foo :: State Int Int
foo = state $ \a -> (a, a)

类型构造函数State 还在,只是数据构造函数被隐藏了以支持state。这有点令人困惑,因为它们都被命名为同一个东西。

【讨论】:

  • 啊,是的,感谢您对问题本身的回答,以及关于同名类型构造函数和数据构造函数之间区别的额外提醒,这是粗心的常年陷阱。 [咳嗽]。
  • 我不确定是否可以严格调用 State 类型构造函数,它现在是类型别名 (type State s = StateT s Identity)。
  • @DanielFischer 说得很好,将其称为类型别名是否更合适?虽然 GHC 不会很快去除类型别名吗?
【解决方案2】:

代码使用State 类型同义词编译得很好。你只需要

import Control.Monad.State

【讨论】:

  • 感谢您的回答。我不知道,但我怀疑你是第一个,但我将复选标记授予 jozefg 使用 ESP 来确定我可能想知道一些相关的事实。不过很高兴为您的回答 +1。
猜你喜欢
  • 2013-02-20
  • 2016-06-15
  • 1970-01-01
  • 1970-01-01
  • 2011-04-26
  • 2013-03-06
  • 2020-03-29
  • 1970-01-01
  • 2012-08-08
相关资源
最近更新 更多