Распространение государственной монады - PullRequest
3 голосов
/ 22 марта 2011

У меня есть следующая функция для обхода «краев» «графика» моего игрового мира. Это меняет состояние мира - в частности, местоположение игрока. Мне нужно сообщить сообщение, предупреждающее игрока об их изменении в локации.

Так что я могу либо вернуть кортеж (message, newWorld), либо использовать монаду State. (Верно? Я новичок в этом деле.)

Вот моя попытка монадного подхода:

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 и так далее? Должен ли я стараться, чтобы эта государственная монада проходила как можно дольше? Должен ли я видеть много MonadState ... в моих сигнатурах?

1 Ответ

4 голосов
/ 22 марта 2011

Вот один способ думать об этом: runState требует начального состояния в качестве параметра.Где это начальное состояние доступно в вашем коде?Вот как далеко должна распространяться монада состояний.

Обратите внимание, что runState инкапсулирует вычисления с состоянием, так что если у вас есть два runState вычисления рядом, они не будут видеть состояния друг друга(если вы не передадите результат от одного к другому.) Это также должно дать вам подсказку, как далеко «вверх» должен быть runState.

...