Как я могу переписать произвольно вложенное поле в структуру JSON, используя линзы Haskell?

Я хотел бы сделать следующий тест:

it "can rewrite a field from an object" $ do
  let _42 = 42 :: Int
      nested =  object [ "foo" .= _42, "baz" .= object [ "bar" .= _42 ] ]
                                           ]
  rewrite "bar" nested  `shouldBe` object [ "foo" .= _42
                                          , "baz" .= object [ "bar" .= ("XXXXXXXX" :: Text) ]
                                          ]

Кажется, мне нужно что-то из Control.Lens.Plated вроде переписать как или transform, но мне не удается заставить его работать, вероятно, из-за отсутствия глубокого понимания линз.

Мне удалось изменить один слой, используя следующий код, но я хотел бы использовать его для вложенных полей.

 rewrite' field value = value & key field %~ const "XXXXXXXX"

person insitu    schedule 22.06.2017    source источник
comment
Делает ли \field -> transform (rewrite' field) то, что вы хотите? (Просто предположение - я тоже не эксперт по объективам)   -  person user2407038    schedule 22.06.2017


Ответы (1)


Один из подходов заключается в использовании transformOn вместе с deep, чтобы получить точный контроль над тем, где применяется преобразование.

ghci> let nested = object [ "foo" .= 42, "baz" .= object [ "bar" .= 42 ] ]
ghci> transformOn (deep $ key "bar") (const "XXXXXXXX") nested
Object (fromList [("foo",Number 42.0),("baz",Object (fromList [("bar",String "XXXXXXXX")]))])

deep ищет в структуре Plated места, где предоставленные Traversal совпадают, а transformOn применяет изменение к каждой из своих целей.

ИЗМЕНИТЬ:

Я только что понял, что transformOn слишком много для этого. Вы можете обойтись только deep и более простыми комбинаторами линз:

ghci> deep (key "bar") %~ const "XXXXXXXX" $ nested
Object (fromList [("foo",Number 42.0),("baz",Object (fromList [("bar",String "XXXXXXXX")]))])

или даже

ghci> deep (key "bar") .~ "XXXXXXXX" $ nested
Object (fromList [("foo",Number 42.0),("baz",Object (fromList [("bar",String "XXXXXXXX")]))])

Семейство функций transform* применяет свои модификации рекурсивно, что является излишним для той модификации, которую вы хотите сделать.

person Carl    schedule 22.06.2017