2

原来的问题

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

这会在此处的 wikibooks 页面中弄乱 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.

附录

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

这个问题的主题围绕着无效的示例代码,以及上面引用的维基书籍页面上的注释框中的警告。该框告诉 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 selection ……这可以解释很多,至少在2-3年前。

4

2 回答 2

7

上面的代码只有一个问题

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。这有点令人困惑,因为它们都被命名为同一个东西。

于 2013-02-22T04:19:11.357 回答
4

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

import Control.Monad.State
于 2013-02-22T04:16:50.963 回答