Опитвам се да напиша малка игра на Haskell и има доста голямо количество състояние, необходимо за предаване. Искам да опитам да скрия състоянието с монадата State
Сега се натъкнах на проблем: функции, които приемат състояние и аргумент, бяха лесни за писане, за да работят в монада състояние. Но има и функции, които просто приемат състоянието като аргумент (и връщат модифицирано състояние или евентуално нещо друго).
В една част от моя код имам този ред:
let player = getCurrentPlayer state
Бих искал да не приема състояние, а вместо това да пише
player <- getCurrentPlayerM
в момента изпълнението му изглежда така
getCurrentPlayer gameState =
(players gameState) ! (on_turn gameState)
и изглеждаше достатъчно просто да го накарам да работи в държавната монада, като го напишем така:
getCurrentPlayerM = do state <- get
return (players state ! on_turn state)
Това обаче предизвиква оплаквания от ghc! Няма екземпляр за (MonadState GameState m0), произтичащ от използване на `get', се казва. Вече бях пренаписал много подобна функция, с изключение на това, че не беше nullary във формата си State monad, така че по предчувствие я пренаписах така:
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?
- Защо не мога да декларирам типа, който моята заобиколна функция всъщност има?