我正试图在Haskell写一个小游戏,并且有相当多的状态需要传递.我想尝试用状态monad隐藏状态
现在我遇到了一个问题:带状态和参数的函数很容易写入状态monad中.但也有一些函数只是将状态作为参数(并返回修改后的状态,或者可能是其他东西).
在我的代码的一部分中,我有这一行:
let player = getCurrentPlayer state
Run Code Online (Sandbox Code Playgroud)
我希望它不采取状态,而是写
player <- getCurrentPlayerM
Run Code Online (Sandbox Code Playgroud)
目前,它的实现看起来像这样
getCurrentPlayer gameState =
(players gameState) ! (on_turn gameState)
Run Code Online (Sandbox Code Playgroud)
通过这样编写它似乎很简单,使它在State monad中工作:
getCurrentPlayerM = do state <- get
return (players state ! on_turn state)
Run Code Online (Sandbox Code Playgroud)
然而,这引起了ghc的抱怨!它说,没有使用"get"产生的(MonadState GameState m0)实例.我已经重写了一个非常相似的函数,除了它的状态monad形式不是nullary,所以在预感中,我重写了这样:
getCurrentPlayerM _ = do state <- get
return (players state ! on_turn state)
Run Code Online (Sandbox Code Playgroud)
果然,它的确有效!但当然我必须把它称为getCurrentPlayerM(),我觉得有点傻.传递参数是我想要首先避免的!
另外一个惊喜:看看我得到的ghci类型
getCurrentPlayerM :: MonadState GameState m => t -> m P.Player
Run Code Online (Sandbox Code Playgroud)
但是如果我尝试在我的代码中明确地设置它,我会得到另一个错误:"约束MonadState GameState m中的非类型变量参数"以及允许它的语言扩展的提议.我想这是因为我的GameState是一种类型,而不是类型类,但是为什么它在实践中被接受,但是当我试图明确它时,我更加困惑.
总结一下: