«состояние отображения экземпляра, где» не компилируется

#haskell #monads #state-monad

#haskell #монады #состояние-монада

Вопрос:

Это код состояния Монады, который я пытаюсь выяснить

 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
 

Я пытаюсь создать состояние как экземпляр Show, чтобы я мог видеть действие getState и putState count в командной строке ghci.

Любой учебник или ссылка на материал State Monad тоже были бы хороши.

Комментарии:

1. Если вы получаете ошибки компилятора, которые хотите решить, вы всегда должны указывать их в вопросе.

Ответ №1:

Вот 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)"]
 

Ответ №2:

В Haskell классы типов классифицируют только типы одного и того же типа. Monad классифицирует типы типов * -> * , в то время как Show классифицирует типы типов * . Ваш тип состояния имеет вид * -> * , поэтому с вашим экземпляром нет проблем Monad , но есть проблема с вашим 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:

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

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


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

Комментарии:

1. Есть ли какой-нибудь визуальный способ показать, как getState putState работает и в приведенном выше коде?

2. @Qin — я не уверен, о чем вы спрашиваете, но, возможно, вы ищете runState . Я добавил пример.

3. ввод runState говорит Not in scope: 'runState' , нужно ли импортировать какой-либо модуль?