2011-11-01 56 views
1

這是國家單子代碼我試圖找出「實例顯示狀態」沒有編譯

data State a = State (Int -> (a, Int)) 
instance Monad State where 
    return x = State (\c -> (x, c))  
    State m >>= f = State (\c -> 
     case m c of { (a, acount) -> 
      case f a of State b -> b acount}) 

getState = State (\c -> (c, c)) 
putState count = State (\_ -> ((), count)) 

instance Show State where -- doesn't work 
    show (State a) = show a -- doesn't work 

我努力使國家作爲展會的實例,這樣我可以看到的動作在ghci提示符上輸入getStateputState count

任何教程或鏈接到狀態Monad材料也不錯。

+5

如果您遇到想要解決的編譯器錯誤,則應始終將其置於該問題中。 – sth

回答

3

以下是對State Monad的一個很好的(也是我個人最喜歡的)解釋:Learn You A Haskell。 (對於一般學習Haskell來說也是一個很好的資源)。

您可能已經注意到,函數不是Haskell中Show類型類的一部分。並且由於State基本上只是某種類型功能的newtype包裝器,因此無法生成(有意義的)StateShow的實例。


下面是使用國家單子從LYAH代碼:

import Control.Monad.State -- first, import the state monad 

pop :: State Stack Int 
pop = State $ \(x:xs) -> (x,xs) 

push :: Int -> State Stack() 
push a = State $ \xs -> ((),a:xs) 

stackManip :: State Stack Int 
stackManip = do 
    push 3 
    a <- pop 
    pop 

下面是從ghci在行動代碼:

*Main> runState stackManip [1,2,3] 
(1,[2,3]) 

元組的fst是結果,而該元組的snd是(修改)狀態。

+0

是否有任何可視化的方式來顯示'getState'和'putState'如何在上面的代碼中工作? – nobody

+0

@秦 - 我不確定你在問什麼 - 但也許你正在尋找'runState'。我已經添加了一個例子。 –

+0

打字runState說'不在範圍內:'runState''我必須導入任何模塊? – nobody

5

這裏是一個Show實例,可以幫忙看看這是怎麼回事:

instance Show a => Show (State a) where 
    show (State f) = show [show i ++ " => " ++ show (f i) | i <- [0..3]] 

然後,你可以這樣做:

*Main> getState 
["0 => (0,0)","1 => (1,1)","2 => (2,2)","3 => (3,3)"] 
*Main> putState 1 
["0 => ((),1)","1 => ((),1)","2 => ((),1)","3 => ((),1)"] 
4

在Haskell中,類型類分類只有類型相同那種的。 Monad分類種類* -> *,而Show分類種類*。你的狀態類型有* -> *,這就是爲什麼你的Monad實例沒有問題,但是你的Show實例有問題。 State被稱爲「類型構造函數」,因爲它消耗一個類型以產生另一種類型。認爲它有點像類型級別的函數應用。因此,您可以將特定類型,並實例是:

instance Show (State Char) where 
    show _ = "<< Some State >>" 

現在,這是不是一個非常有用的情況下,嘗試像Sjoerd的建議得到一個更有意義的顯示實例。注意他的版本使用通用類型約束

instance (Show a) => Show (State a) where 
    -- blah blah 

通用類型是a,並且約束是(Show a) =>,換句話說,a本身必須是Show一個實例。