I am trying to give Monad and MonadState instances for State' that counts the number of (>>=), return, get and put operations.
data Counts = Counts { binds :: Int
, returns :: Int
, gets :: Int
, puts :: Int
}
newtype State' s a = State' { runState' :: (s, Counts) -> (a, s, Counts) }
That's what I have already done, and as far as I understand what is going on, this code should work:
instance Monad State' where
return = State' ( \(s, counts) -> (x, s, counts mappend oneReturn))
(>>=) st f = State' ( \(s, counts) -> let (x, s', counts') = runState' (s, counts) in runState' ((f x), (s', counts' mappend oneBind)) )
instance Monad m => MonadState m State' where
get = State' ( \(s, counts) -> (s, s, counts mappend oneGet) )
put st = State' ( \(s, counts) -> ((), st, counts mappend onePut) )
But I get this error message:
Expecting one more argument to
‘State'’
Expected kind‘* -> *’, but‘State'’has kind‘* -> * -> *’
Why?
The point is in the sentence
Expected kind ‘* -> *’, but ‘State'’ has kind ‘* -> * -> *’
If you check the kind of State' with GHCi using :k command you will see that State' has kind * -> * -> * which simply speaking means that it requires to be parametrized by two types of kind * to produce finalized * type. Monads are as you see restricted to * -> *. For instance Maybe is a Monad, while Maybe Int is not.
To fix your case you will need to apply the state type to State' and then you will be able to declare it as a Monad:
instance Monad (State' s) where
The error in the second part is a bit conceptual – what is m in your declaration? MonadState is a subclass of Monad, so every instance of MonadState is also instance of Monad. With this in mind the correct notation should make some sense:
instance MonadState s (State' s) where
You don't want to mention this Monad – it is derivable from the class declaration.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With