Что не так с моими подписями типа get и put?

Я пытаюсь сделать StateMonadPlus экземпляром MonadState.

data StateMonadPlus s a = StateMonadPlus (s -> Either String (a, s))

instance MonadState s (StateMonadPlus s) where
    -- get :: StateMonadPlus s
    get = StateMonadPlus (\s -> Right (s, s))
    -- put :: s -> StateMonadPlus ()
    put s = StateMonadPlus (\_ -> Right ((), s))

Код компилируется просто отлично, но когда я раскомментирую типы get и put, он жалуется, что

A3.hs:17:5: Misplaced type signature: get :: StateMonadPlus s

A3.hs:19:5: Misplaced type signature: put :: s -> StateMonadPlus ()

Что не так с типами?


person Chiel ten Brinke    schedule 03.10.2013    source источник


Ответы (1)


Вы получаете ошибку компилятора, потому что сигнатуры типов там не принадлежат. Вы не можете поместить сигнатуру типа в объявление экземпляра, потому что тип уже определен сигнатурой в объявлении класса.

Однако это не означает, что подписи будут правильными, если вы раскомментируете их. Подпись типа get и put

get :: MonadState s m => m s

put :: MonadState s m => s -> m ()

так что "правильные" подписи типа

get :: StateMonadPlus s s

put :: s -> StateMonadPlus s ()

При написании экземпляров класса я обычно делаю то же самое, что и вы в своем вопросе, - я пишу подпись типа, но комментирую ее, чтобы было легче понять экземпляр, если мне нужно вернуться к нему позже.

person Chris Taylor    schedule 03.10.2013