如何以优雅的方式“改变”大对象中的单个值?

时间:2013-07-08 03:22:57

标签: haskell

例如,我有

data ShipDesign = ShipDesign {
      offense :: Offense
    , defense :: Defense
    , maxHealth :: Integer
    , repairRate :: Integer
    , stealth :: Integer
    , radar :: Integer
    , speed :: Integer
    , shipType :: String
    ...
    }

现在我想改变防守。 已知的方法是:

changeDefense :: (Defense -> Defense) -> ShipDesign -> ShipDesign
changeDefense fDef sd@(ShipDesign o d m rr s r sp st ...) = ShipDesign o (fDef d) m rr s r sp st ...

这不优雅。特别是在游戏中,每步只更改几个值。

我的问题是:是否有更优雅的方式更改单个值的库,设计模式或其他方式?

2 个答案:

答案 0 :(得分:15)

是的,您可以使用记录更新记谱法:

 changeDefense :: (Defense -> Defense) -> ShipDesign -> ShipDesign
 changeDefense fDef sd = sd { defense = fDef (defense sd) }

但是,当您使用它时,记录更新表示法的局限性将显示出来,并且您将需要更强大的功能。那时,您应该开始了解lenses

答案 1 :(得分:3)

我想知道为什么没有人提出镜片?

我推荐Gabriel Gonzalez的简短介绍: http://www.haskellforall.com/2013/05/program-imperatively-using-haskell.html?m=1

编辑:哦......我读完了最后一句话。但这个建议仍然存在。