2

这是我试图弄清楚的状态单子代码

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

我正在尝试将 State 作为 Show 的实例,以便我可以看到ghci 提示符的动作getState和动作。putState count

任何指向 State Monad 材料的教程或链接也会很好。

4

3 回答 3

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)"]
于 2011-11-01T13:32:50.637 回答
5

在 Haskell 中,类型类只对相同种类的类型进行分类。Monad 对 kind 类型进行* -> *分类,而 Show 对 kind 类型进行分类*。您的 State 类型有 kind * -> *,这就是为什么您的实例没有问题Monad,但您的实例问题ShowState被称为“类型构造函数”,因为它消耗一个类型以产生另一种类型。认为它有点像类型级别的函数应用程序。因此,您可以应用特定类型并创建实例:

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

现在,这不是一个非常有用的实例,尝试类似 Sjoerd 的建议以获得更有意义的 Show 实例。请注意,他的版本使用带有约束的泛型类型

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

泛型类型是a,约束是(Show a) =>,换句话说,a它本身必须是 的实例Show

于 2011-11-01T18:12:23.513 回答
3

这是对 State Monad 的一个很好的(我个人最喜欢的)解释: Learn You A Haskell。(也是学习 Haskell 的一个很好的资源)。

你可能已经注意到函数不是ShowHaskell 中类型类的一部分。而且由于State基本上只是某些newtype类型函数的包装器,因此您不能创建.StateShow


这是使用 LYAH 的 State Monad 的代码:

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元组的 是(修改后的)状态。

于 2011-11-01T13:16:07.923 回答