镜头访问映射键

Lens access Map Key

我在使用 Lens 库访问地图数据类型时遇到了一些问题。

data Card
  = Ferme
  | Boulangerie

data PlayerState = PlayerState {
  _psCards      :: Map Card Int,
  } deriving (Show)


data GameState = GameState {
  _gsPlayers      :: [PlayerState]
                 } deriving (Show)

我无法访问 Map

step :: (MonadState s m, HasGameState s, MonadIO m) => m ()
step = do
    i <- use $ gsPlayers . ix 0 . psCards . ix Ferme

出现以下错误:

    • Could not deduce (Monoid Int) arising from a use of ‘ix’
      from the context: (MonadState s m, HasGameState s, MonadIO m)
        bound by the type signature for:
                   step :: forall s (m :: * -> *).
                           (MonadState s m, HasGameState s, MonadIO m) =>
                           m ()

这是因为我在同一行中使用 ix 和不同的参数吗?

这是因为 ix 是一个遍历,但 use 需要一个镜头。区别在于 Lens 总是只有一个目标。遍历可以有零个或多个。在检索值时期望透镜的组合器在给定遍历时会意外地尝试将多个值组合在一起作为 Monoid。 (它来自 ConstApplicative 实例,特别是。)该尝试不会在您的情况下进行类型检查,因为目标类型不存在此类实例,因此您会收到该错误消息。

您可能需要 preuse 组合器而不是 use,以说明可能不存在的值。