2013-02-22 114 views
2

原始問題

最近版本的Haskell(> 7.4.2?)帶有一個mtl包,它不再提供一個狀態構造函數本身,而是提供一個狀態函數。wikibooks中的Haskell狀態示例:修復每個當前Haskell?

這打亂了國家的例子在維基頁面在這裏:http://en.wikibooks.org/wiki/Haskell/Understanding_monads/State

有人可以顯示如何修改以下標題的例子「引進國家」?這是小功能rollDie和rollDice。

在頁面的前面有一個註釋框,標題爲「State Monad的定義」,它總體上描述了要做什麼,但對我來說太模糊了。

另外,我並不清楚導入和包是如何工作的,所以對這個例子來說一個可能相關的事情可能是指定需要什麼導入,因爲它們也可能已經改變。

謝謝!

源代碼

------- 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中的更改,某些示例代碼無法工作。

我的測試涉及到基於mtl.cabal文件的Haskell Platform 2012.4.0.0,其中包括GHC 7.4.2和MTL,我遲遲未發現它是1.1.1.1。 因此,注意的警告不應該適用,但是示例代碼無效無效。通過這裏的答案建議的更改(更改導入Control.Monad到Control.Monad.State)確實解決了問題。但顯然這是解決了一些與之前的更改有關的問題,而不是註釋中引用的MTL 2.x。

我已經看過GHC 7.6.2的源代碼了,在那裏我根本找不到MTL庫。相反,與狀態相關的文件位於庫/變換器/控制/ Monad/Trans /狀態中。然後,我採取了一系列令人困惑的彎路,包括當前沒有使用GHC的Haskell平臺遲於7.4.2(即:無7.6.2)的問題。

然後我發現MTL文檔(http://www.haskell.org/haskellwiki/Monad_Transformer_Library),它指向這個計算器Q &答:mtl, transformers, monads-fd, monadLib, and the paradox of choice ...哪種類型的解釋了很多,至少在23年以前。

+0

我認爲這些函數適用於MTL版本2.12(當前版本)。你爲什麼認爲他們不?你可以發佈你在嘗試它們時得到的錯誤(和你的完整代碼)嗎? – 2013-02-22 03:10:30

+0

我已經添加了我嘗試過的代碼,它是從wikibooks頁面複製的,我認爲是逐字的。根據我指出的註釋框,我相當確定它不會工作,並且錯誤消息(缺少狀態構造函數或類)與註釋所預測的一樣。 – gwideman 2013-02-22 03:25:08

回答

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。這有點令人困惑,因爲它們都被命名爲相同的東西。

+0

啊,是的,謝謝你對這個問題本身的回答,以及關於類似命名的類型構造函數和數據構造函數之間的區別的額外提醒,這是一個常常陷入困境的陷阱。 [咳嗽]。 – gwideman 2013-02-22 10:25:02

+1

我不確定是否可以嚴格調用'State'類型構造函數,它現在是一個類型別名('type State s = StateT s Identity')。 – 2013-02-22 14:49:49

+1

@DanielFischer這是一個很好的觀點,將它稱爲類型別名會更合適嗎?雖然GHC不會很快地去掉別名? – jozefg 2013-02-22 16:33:50

4

該代碼與State類型同義詞編譯得很好。你只需要

import Control.Monad.State 
+0

感謝您的回答。我不知道,但我懷疑你是第一個髮型,但是我將這個複選標記授予jozefg使用ESP來確定我可能想知道一些相關的事實。很高興+1你的答案。 – gwideman 2013-02-22 10:27:41