问题
This is the State Monad code I am trying to figure out
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
I am trying to make State as instance of Show so that I can see the action of getState
and putState count
on the ghci prompt.
Any tutorial or link to State Monad material would be nice too.
回答1:
Here's is a Show
instance that can help see what's going on:
instance Show a => Show (State a) where
show (State f) = show [show i ++ " => " ++ show (f i) | i <- [0..3]]
Then you can do:
*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)"]
回答2:
In Haskell, typeclasses classify only types of the same kind. Monad classifies types of kind * -> *
, while Show classifies types of kind *
. Your State type has kind * -> *
which is why there isn't a problem with your Monad
instance, but there is a problem with your Show
instance. State
is called a "type constructor" because it consumes a type in order to produce another type. Think of it sort of like function application at the type level. You can therefore apply a specific type and make instances of that:
instance Show (State Char) where
show _ = "<< Some State >>"
Now, this isn't a very useful instance, try something like Sjoerd's suggestion to get a more meaningful Show instance. Notice that his version uses a generic type with a constraint.
instance (Show a) => Show (State a) where
-- blah blah
The generic type is a
, and the constraint is (Show a) =>
, in other words, a
itself must be an instance of Show
.
回答3:
Here's a great (and personally, my favorite) explanation of the State Monad: Learn You A Haskell. (Also a great resource for learning Haskell in general).
You may have noticed that functions aren't part of the Show
typeclass in Haskell. And since State
is basically just a newtype
wrapper for functions of certain types, you can't make a (meaningful) State
instance of Show
.
Here's code using the State Monad from 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
And here's that code in action from ghci
:
*Main> runState stackManip [1,2,3]
(1,[2,3])
The fst
of the tuple is the result, and the snd
of the tuple is the (modified) state.
来源:https://stackoverflow.com/questions/7966956/instance-show-state-where-doesnt-compile