I'm trying to make StateMonadPlus an instance of 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))

The code compiles just fine, but when I uncomment the types of get and put, it's complaining that

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

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

What's wrong with the types?

有帮助吗?

解决方案

You get a compiler error because the type signatures don't belong there. You can't put a type signature in an instance declaration, because the type is already determined by the signature in the class declaration.

However, that's not to say that the signatures would be correct if you uncommented them. The type signature of get and put is

get :: MonadState s m => m s

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

so the 'correct' type signatures are

get :: StateMonadPlus s s

put :: s -> StateMonadPlus s ()

When writing class instances I tend to do the same thing as you have done in your question - I write the type signature but comment it out, so that it's easier to understand the instance if I need to come back to it later.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top