我有以下功能可以绕过我游戏世界“图形”的“边缘”。它改变了世界的状态 - 特别是玩家的位置。我需要报告一条消息,提醒玩家他们的位置变化。
所以我可以返回(message,newWorld)的元组,或者我可以使用State monad。 (对吧?我对这些东西不熟悉。)
这是我对monad方法的尝试:
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)
问题是,现在调用 walk
的函数有一个State monad来处理。我是runState
它在那里,还是我有这个功能也使用State monads,如下所示:
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"
那么parseWalk
的来电怎么样?等等?我应该尽量让这个州的monad继续传递吗?我的类型签名中是否应该看到很多MonadState ...
?
答案 0 :(得分:4)
这是思考它的一种方式:runState
需要初始状态作为其参数。您的代码中的初始状态在哪里?这就是状态monad需要传播的距离。
请注意runState
封装了有状态计算,因此如果你并排进行两次runState
次计算,他们就不会看到彼此的状态(除非你将结果从一个传递给另一个。)这也应该给你一个暗示runState
需要多远的提示。