2017-06-22 54 views
2

我想作以下測試通過:如何使用haskell鏡頭重寫JSON結構中的任意嵌套字段?

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.Platedrewrite狀或transform,但我不能管理,使其工作,可能是由於缺少深刻的理解鏡頭。

我設法改變使用下面的代碼的單層,但想利用它嵌套字段。

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

'\ field - > transform(rewrite'field)'做你想做的事嗎? (只是猜測 - 我也不是鏡頭專家) – user2407038

回答

2

一種方法是使用具有deep沿transformOn在其中施加改造得到精確的控制。

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*系列函數遞歸的應用及其修改,這是矯枉過正要進行修改。