在lens-aeson

时间:2016-02-24 18:34:01

标签: haskell lens aeson

我有以下一些代码,我对它不满意:


import Data.Aeson.Lens
import Data.Aeson.Types
import Data.Text hiding (foldl, map)

path :: (Applicative f, AsValue t) => [Text] -> (Value -> f Value) -> t -> f t path [] = error "No path provided" path (i:is) = foldl (.) (key i) (map key is)

path意味着成为嵌套JSON对象的镜头。例如:

"{ \"a\": { \"b\": 8} }" ^? path ["a", "b"] == Just (Number 8.0)

目前这有效,但有些明显的缺点是功能不完全。

我尝试了以下定义:

  1. path is = foldl (.) id (map key is)
    
  2. path [] = id
    path (i:is) = foldl (.) (key i) (map key is)
    
  3. -- This one doesn't compile
    path [] = _Object
    path (i:is) = foldl (.) (key i) (map key is)
    
  4. 使用这些定义运行与上面相同的代码块会产生Nothing,而不是预期的8

    我几乎可以肯定这是一个类型杂耍的例子,我只是缺少,但我无法弄清楚如何使用一个完整的功能来完成这项工作。预期的行为是path []Lens,它专注于整个json对象。

1 个答案:

答案 0 :(得分:2)

对空案例使用_Value

> ("null" :: String) ^? _Value
Just Null
> ("null" :: String) ^? (foldl (.) _Value $ map key ["foo", "bar"])
Nothing
> ("{ \"a\": { \"b\": 8} }" :: String) ^? (foldl (.) _Value $ map key ["a", "b"])
Just (Number 8.0)

如您所描述的那样path不能是Lens,因为它是部分的(正如您所提到的!),最多只有Traversal。但是,如果您确定自己在做什么,那么可以使用signularTraversal转换为Lens