«Экземпляр Show State where» не компилируется - PullRequest
2 голосов
/ 01 ноября 2011

Это код государственной монады, который я пытаюсь выяснить

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, чтобы я мог видеть действие getState и putState count в приглашении ghci.

Любой учебник или ссылка на материал государственной монады тоже подойдет.

Ответы [ 3 ]

5 голосов
/ 01 ноября 2011

Вот пример 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)"]
5 голосов
/ 01 ноября 2011

В Haskell классы типов классифицируют только типы одного и того же вида . Monad классифицирует типы вида * -> *, а Show классифицирует типы вида *. Тип вашего состояния имеет тип * -> *, поэтому с вашим экземпляром * 1006 нет проблем, но - это проблема с вашим экземпляром Show. State называется "конструктором типов", потому что он потребляет тип для создания другого типа. Думайте об этом как о приложении функции на уровне типа. Поэтому вы можете применить определенный тип и создать его экземпляры:

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

Теперь, это не очень полезный экземпляр, попробуйте что-то вроде предложения Sjoerd, чтобы получить более значимый экземпляр Show. Обратите внимание, что в его версии используется универсальный тип с ограничением .

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

Общий тип - a, а ограничение - (Show a) =>, другими словами, a сам по себе должен быть экземпляром Show.

3 голосов
/ 01 ноября 2011

Вот отличное (и лично мое любимое) объяснение Государственной монады: Learn You A Haskell .(Также отличный ресурс для изучения Haskell в целом).

Возможно, вы заметили, что функции не являются частью класса типов Show в Haskell.А поскольку State является просто оболочкой newtype для функций определенных типов, вы не можете создать (осмысленный) State экземпляр Show.


Вот код, использующийState Monad от 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кортежа является (измененным) состоянием.

...