Монад фасад для MonadState в Haskell

Предыстория: я создаю игру с монадой с сохранением состояния для чтения и записи изменений в глобальном состоянии игры.

Я хотел бы разделить мою игру на компоненты, такие как "Персонажи", предоставляя доменным способом взаимодействия этих компонентов с глобальным состоянием. В идеале это может быть определение конкретных действий в форме MonadState Character m => m a что я мог бы использовать, но каждый такой m a будет принимать изменения на родителя (глобальное состояние).

Я искал возможность конвертировать монады состояний или предоставлять интерфейс из одной монады состояний в другую, но конкретный язык для этого выходит за рамки моих знаний. Я также уже использую линзы, и мне интересно, могу ли я что-нибудь с ними сделать.

РЕДАКТИРОВАТЬ:

Я хотел бы иметь возможность сделать что-то вроде moveCharacter :: MonadState Character m => Int -> Int -> m ()

и есть что выполнить move :: MonadState World m => Int -> Int -> m () внутри. В основном, абстрагируя мир от специфики персонажа.

Спасибо!

2 ответа

Похоже, вы ищете Zoom, который позволяет преобразовать действие с состоянием на вид объектива в действие с состоянием на источник объектива.

На самом деле вам нужны 2 функции преобразования: одна для извлечения персонажа из мира и другая для изменения мира с помощью измененного персонажа. Вы можете соединить их так:

extractCharacter :: World -> Character
extractCharacter = error "Tried to call placeholder function"

replaceCharacter :: World -> Character -> World
replaceCharacter = error "Tried to call placeholder function"

runCharacterSubroutine :: (Functor m) =>
  StateT Character m a -> StateT World m a
runCharacterSubroutine act = StateT $ \w ->
  fmap (\(a,c') -> (a,replaceCharacter w c')) $
  runStateT act (extractCharacter w)

В вашей игре вы, вероятно, хотите что-то более сложное, но это просто вопрос добавления дополнительного параметра в extractCharacter а также replaceCharacter

Обратите внимание, что функция, которую я дал, работает, только если StateT находится на вершине стека трансформаторных монад. Если это не так: вам придется использовать mmorph пакет

Другие вопросы по тегам