我正在尝试将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 ()
这些类型有什么问题?
答案 0 :(得分:3)
您收到编译器错误,因为类型签名不属于那里。您不能在实例声明中放置类型签名,因为类型已经由类声明中的签名确定。
但是,如果您取消注释,那并不是说签名是正确的。 get
和put
的类型签名是
get :: MonadState s m => m s
put :: MonadState s m => s -> m ()
所以'正确'类型签名是
get :: StateMonadPlus s s
put :: s -> StateMonadPlus s ()
在编写类实例时,我倾向于做与你在问题中所做的相同的事情 - 我写了类型签名但是将其注释掉,这样如果我需要稍后再回来它就更容易理解实例。