改变Haskell中记录的值

时间:2017-11-25 02:04:55

标签: haskell state records

我对Haskell很陌生并且练习,我决定制作一款d& d风格的游戏,其中战斗基于掷骰子,而拥有更多数字的人则获胜。但是,我对如何更改记录的值并更改记录的全局值感到困惑。

这是我的记录代码:

data PlayerStats = PlayerStats { health :: Health
                              ,mana :: Mana
                              ,inventory :: [Items]   }deriving (Show,Eq)




defaultStats = PlayerStats {health = 100, mana = 50, inventory = []}

如果玩家输掉骰子,这就是我的功能:

takeDamage:: State PlayerStats ()
takeDamage = do
         let h = defaultStats health 
         h <- get
         put $ (h - 10)

我在互联网上寻找像我这样的问题的解决方案,但没有找到任何东西,所以我认为这对我所处的其他人有用。

1 个答案:

答案 0 :(得分:3)

首先,defaultStats :: PlayerStats,这是一个记录,而不是一个函数,所以:

defaultStats health

没有意义。另一方面,health :: PlayerStats -> Health是一个函数,所以

health defaultStats

更有意义,但基本上是常数100,因为那是health的{​​{1}}。但是,在这种情况下,它没有意义,因为你立即引入一个新的defaultStats,绑定到h,(假设getState)得到来自Control.Monad.Trans.State PlayerStats的当前State。请注意,Monad将是整个h,而不仅仅是PlayerStats组件。

记录更新确实会从现有记录中创建一条新记录,其中一个或多个字段将替换为新值。在这种情况下,您希望将health字段替换为当前值减去health

10

在这里,我们从takeDamage = do ps <- get put $ ps { health = health ps - 10 } PlayerStats获取当前StateMonad,然后ps为新put基于当前的一个,但PlayerStats字段设置为当前health减去health。在记录更新语法中,10左侧的health表示字段名称,右侧的=表示获取health的访问者函数来自现有记录的字段。

health后面跟着get很常见,有一个put函数,它接受一个转换状态的函数,并用modify和{{包装它1}}:

get

记录更新语法是一个巨大的Haskell疣。您可能需要查看lenses,这样可以非常轻松地更新put takeDamage = modify $ \ps -> ps { health = health ps - 10 } 中的字段(尽管当您陷入困境时收到的错误消息会让您的大脑融化)。

修改

如果你想看看你的玩家是否失去了所有健康状况,你可以让State函数返回一个Monad来表明该玩家是否幸存下来:

takeDamage