I would like to make the following test pass:
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) ]
]
It seems that what I want is something from Control.Lens.Plated
like rewrite like or transform but I cannot manage to make it work, probably due to missing deep understanding of lenses.
I managed to change a single layer using the following code but would like to leverage that to nested fields.
rewrite' field value = value & key field %~ const "XXXXXXXX"
One approach is to use transformOn
along with deep
to get precise control over the where the transformation is applied.
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
searches a Plated
structure for locations where the provided Traversal
matches, and transformOn
applies a change to each of its targets.
EDIT:
I just realized transformOn
is massive overkill for this. You can get away with just deep
and simpler lens combinators:
ghci> deep (key "bar") %~ const "XXXXXXXX" $ nested
Object (fromList [("foo",Number 42.0),("baz",Object (fromList [("bar",String "XXXXXXXX")]))])
or even
ghci> deep (key "bar") .~ "XXXXXXXX" $ nested
Object (fromList [("foo",Number 42.0),("baz",Object (fromList [("bar",String "XXXXXXXX")]))])
The transform*
family of functions applies its modifications recursively, which is overkill for the modification you want to make.