Propaganda of the state monad

I have the following function for walking on the "edges" of the "graphics" of my game world. This changes the state of the world - in particular, the location of the player. I need to report a message warning the player about their change in location.

So, I could either return the tuple (message, newWorld), or I could use the state monad. (Right? I'm new to this.)

Here is my attempt at a monad approach:

walk dir = do world <- get let attempt = filter (\e -> edgeDirection e == dir) $ edges edges = (worldEdges world) M.! playerLoc playerLoc = playerLocation $ worldPlayer world case attempt of [] -> return "You can't go that way." (edge : _) -> do put world' return message where world' = world { worldPlayer = player' } player' = (worldPlayer world) { playerLocation = loc } loc = edgeLocation edge message = "You go " ++ (downcase $ show dir) 

The fact is that now the function that calls walk has a state monad. I am here runState , or I have this function using state monads, for example:

 parseWalk dir = let direction = case dir of ('e' : _) -> Just East ('n' : _) -> Just North ('s' : _) -> Just South ('w' : _) -> Just West ('u' : _) -> Just Up ('d' : _) -> Just Down _ -> Nothing in case direction of Just d -> walk d Nothing -> return "You can't go that way" 

Then what about parseWalk caller, etc.? Should I try to keep this state monad as long as possible? Should I see a lot of MonadState ... in my type signatures?

Yours faithfully,

Confused in california

+3
source share
1 answer

Here's one way to think: runState requires its initial state. Where is this initial state available in your code? How far should the state monad flourish.

Note that runState encapsulates a runState calculation, so if you have two runState calculations side by side, they will not see each other's state (unless you pass the result from one to the other). It should also give you a hint about how upstream the runState should be.

+4
source

All Articles