Question

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?

Was it helpful?

Solution

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top