Я пытаюсь написать небольшую игру на Haskell, и нужно передать изрядное количество состояний. Я хочу попытаться скрыть состояние с помощью монады состояния
Теперь я столкнулся с проблемой: функции, которые принимают состояние и аргумент, легко написать для работы в монаде состояний. Но есть также функции, которые просто принимают состояние в качестве аргумента (и возвращают измененное состояние или, возможно, что-то еще).
В одной части моего кода у меня есть такая строка:
let player = getCurrentPlayer state
Я бы хотел, чтобы он не принимал состояние, а вместо этого писал
player <- getCurrentPlayerM
в настоящее время его реализация выглядит так
getCurrentPlayer gameState =
(players gameState) ! (on_turn gameState)
и казалось достаточно простым, чтобы заставить его работать в монаде State, написав это так:
getCurrentPlayerM = do state <- get
return (players state ! on_turn state)
Однако это вызывает жалобы со стороны ghc! В нем говорится, что нет экземпляра для (MonadState GameState m0), возникающего из-за использования `get '. Я уже переписал очень похожую функцию, за исключением того, что она не была нулевой в форме монады состояния, поэтому, догадываясь, я переписал ее следующим образом:
getCurrentPlayerM _ = do state <- get
return (players state ! on_turn state)
И действительно, это работает! Но, конечно, я должен называть это getCurrentPlayerM (), и мне кажется, что это немного глупо. В первую очередь я хотел избежать вступления в спор!
Дополнительный сюрприз: глядя на его тип в ghci, я получаю
getCurrentPlayerM :: MonadState GameState m => t -> m P.Player
но если я попытаюсь установить это явно в моем коде, я получаю еще одну ошибку: «Аргумент без переменной типа в ограничении MonadState GameState m» и предложение расширения языка, чтобы разрешить это. Я полагаю, это потому, что мой GameState является типом, а не классом типов, но почему он принят на практике, но не когда я пытаюсь выразить это явно, меня больше смущает.
Итак, подведем итоги:
- Почему я не могу писать нулевые функции в монаде State?
- Почему я не могу объявить тип, который на самом деле имеет моя функция обходного пути?