Ключ карты доступа к объективу

#haskell #haskell-lens

#haskell #haskell-lens

Вопрос:

У меня возникли некоторые проблемы с использованием библиотеки 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 с другим аргументом в одной строке?

Ответ №1:

Это потому, что ix это обход, но use ожидает объектива. Разница в том, что объектив всегда имеет ровно одну цель. Обход может содержать ноль или более. Комбинаторы, которые ожидают, что линзы при извлечении значения как бы случайно пытаются объединить несколько значений вместе как Monoid при заданном обходе. (В частности, он поступает из Applicative экземпляра для Const .) Эта попытка не приводит к проверке типа в вашем случае, потому что для целевого типа не существует такого экземпляра, поэтому вы получаете это сообщение об ошибке.

Вероятно, вы хотите, чтобы preuse combinator вместо use учитывал значение, которого там потенциально нет.