I'm trying to write a little game in Haskell, and there's a fair amount of state necessary to pass around. I want to try hiding the state with the State monad
Now I've run into a problem: functions which take the state and an argument were easy to write to work in the state monad. But there are also functions that just take the state as argument (and return a modified state, or possibly something else).
In one part of my code, I have this line:
let player = getCurrentPlayer state
I would like it to not take state, and instead write
player <- getCurrentPlayerM
currently, its implementation looks like this
getCurrentPlayer gameState =
(players gameState) ! (on_turn gameState)
and it seemed simple enough to make it work in the State monad by writing it like this:
getCurrentPlayerM = do state <- get
return (players state ! on_turn state)
However, that provokes complaints from ghc! No instance for (MonadState GameState m0) arising from a use of `get', it says. I had already rewritten a very similar function, except that wasn't nullary in its State monad form, so on a hunch, I rewrote it like this:
getCurrentPlayerM _ = do state <- get
return (players state ! on_turn state)
And sure enough, it works! But of course I have to call it as getCurrentPlayerM (), and I feel a little silly doing that. Passing in an argument was what I wanted to avoid in the first place!
An additional surprise: looking at its type in ghci I get
getCurrentPlayerM :: MonadState GameState m => t -> m P.Player
but if I try to set that explicitly in my code, I get another error: "Non type-variable argument in the constraint MonadState GameState m" and an offer of a language extension to permit it. I suppose it's because my GameState is a type and not a typeclass, but why it's accepted in practice but not when I try to be explicit about it I'm more confused about.
So to sum up:
- Why can't I write nullary functions in the State monad?
- Why can't I declare the type my workaround function actually has?