Государственные монады: обменять одну модель на другую? - PullRequest
4 голосов
/ 05 августа 2010

Итак, я пишу игру на Хаскеле и выражаю ход игрока как серию функций изменения состояния, которые соотносятся с различными фазами хода.Первоначально это выглядит примерно так:

let game'  = phase1 game
    game'' = phase2 game'
-- etc.

Главный кандидат на государственную монадонность, верно?Это приводит к более элегантному:

do
  phase1
  phase2
-- etc.

Тем не менее, мне кажется, что мне нужно изменить phase1, phase2 и др., Чтобы начать с базового шага "Получение состояния":

phase1 = get >>= \game -> -- ...

Я надеюсь, что есть способ абстрагироваться от этого, чтобы я мог избежать шаблонов как для вызывающей, так и для вызываемой стороны.Я просто слишком новичок, чтобы знать, что это за путь (это мой первый настоящий проект на Haskell).Любой совет?

1 Ответ

8 голосов
/ 05 августа 2010

Ну, это еще не совсем монадосно.Это главный кандидат на моноид Endo .Это приводит к более элегантному

game = mconcat [ phase1, phase2, ... ]

И каждая фаза написана:

phase1 = Endo $ \game -> ...

Вы бы перешли к монаде, если вам нужно было бы вернуть некоторые дополнительные данные вместе с новым состояниемна каждом этапе.В этом случае простая функция сделает ваш шаблон более терпимым:

phase :: (GameState -> GameMonad a) -> GameMonad a
phase f = f =<< get

И тогда будет написана фаза:

phase1 = phase $ \game -> do ...

Но если вы хотите использовать состояние, вы, вероятно,придется дать ему имя (если вы не можете определить точечность, скажем, с помощью получает или data-accessor ), и в этом случае вы не сможете получить намного более краткие результаты, чемфункция и лямбда.

...