小编Har*_*sen的帖子

使用状态monad隐藏显式状态

我正试图在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是一种类型,而不是类型类,但是为什么它在实践中被接受,但是当我试图明确它时,我更加困惑.

总结一下:

  1. 为什么我不能在State monad中编写nullary函数?
  2. 为什么我不能声明我的解决方法函数实际具有的类型?

monads state haskell monomorphism-restriction

10
推荐指数
1
解决办法
982
查看次数

标签 统计

haskell ×1

monads ×1

monomorphism-restriction ×1

state ×1