2011-03-22 35 views
3

我有以下功能,可以漫游我游戏世界的“图形”的“边缘”。它改变了世界的状态 - 特别是玩家的位置。我需要报告一条消息,提醒玩家他们在位置上的变化。所以我可以返回一个(message,newWorld)的元组,或者我可以使用一个状态monad。 (?对我是新来的这些东西。)State 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有国家单子处理功能。难道我runState它在那里,或者我有一个功能,使用国家的单子太多,像这样:

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

由于您正在步行和修改大型数据结构,因此您可能需要查看使用Zipper。 – rampion 2011-03-22 13:52:12

回答

4

这里的思考它的一种方式:runState需要初始状态作为它的参数。代码中的初始状态在哪里可用?这就是国家monad需要传播的程度。

请注意,runState封装了有状态计算,因此如果您有两个并行计算,它们将不会看到彼此的状态(除非您将结果从一个传递给另一个)。给你一个提示runState需要多少“提升”。