如何定义可设置的镜头

时间:2014-12-23 15:23:39

标签: haskell lens

我的Haskell代码中有一个记录类型,我想要定义一个可以用作getter和setter的镜头。代码如下所示:

data Players = Players { _white :: Player
                       , _black :: Player
                       } deriving (Show, Eq)
makeLenses ''Players
_byColor :: Color -> Players -> Player
_byColor White = _white
_byColor Black = _black
byColor col = to (_byColor col)

Players是持有白人和黑人玩家的记录。我希望能够以镜头方式通过颜色获得玩家。 E.g。

players ^. byColor White . hp  -- Access health-points of player

但是,我也希望能够设置按颜色选择的玩家的属性。例如。在状态单子中持有Game字段_players的记录。

let current = White
players . byColor current . hp %= (-1)

使用我当前对byColor的定义,但代码无法编译,并显示以下错误消息:

No instance for (Contravariant Identity)
  arising from a use of `byColor'
Possible fix:
  add an instance declaration for (Contravariant Identity)

我做错了什么?

1 个答案:

答案 0 :(得分:3)

to组合子只制作一个吸气剂,你还没有定义一个完整的镜头。但是,定义完整镜头非常简单,只需根据传入的颜色返回正确的镜头:

byColor :: Color -> Lens' Players Player
byColor White = white
byColor Black = black