Haskell 无法使用镜头从嵌套JSON收集值 编辑
在尝试了几次随机排列之后,我终于得到了答案。但我仍然不明白为什么前者有效,但后者无效:Haskell 无法使用镜头从嵌套JSON收集值 编辑,haskell,haskell-lens,aeson,Haskell,Haskell Lens,Aeson,在尝试了几次随机排列之后,我终于得到了答案。但我仍然不明白为什么前者有效,但后者无效: x ^.. (key "conversations") . values . (key "id") . _String -- vs x ^@.. (key "conversations") . values . (imap (\ _ v -> v ^? key "id")) x ^.. (key "conversations") . values . (key "id") . _String -
x ^.. (key "conversations") . values . (key "id") . _String
-- vs
x ^@.. (key "conversations") . values . (imap (\ _ v -> v ^? key "id"))
x ^.. (key "conversations") . values . (key "id") . _String
-- vs
x ^@.. (key "conversations") . values . (imap (\ _ v -> v ^? key "id"))
原始问题
我有一个JSON,形状如下:
{
"conversations":[
{"id":"abc", ...},
{"id":"abc", ...},
{"id":"abc", ...},
...
]
}
我正在尝试使用以下表达式获取对话。*.id
x ^@.. (key "conversations") . values . (imap (\ _ v -> v ^? key "id"))
…这将导致以下编译器错误:
• Couldn't match type ‘Maybe’
with ‘Const
(base-4.13.0.0:Data.Semigroup.Internal.Endo [(Int, Value)])’
Expected type: IndexedGetting
Int
(base-4.13.0.0:Data.Semigroup.Internal.Endo [(Int, Value)])
BSL.ByteString
Value
Actual type: Indexed
Int
Value
(Const
(base-4.13.0.0:Data.Semigroup.Internal.Endo [(Int, Value)]) Value)
-> BSL.ByteString -> Maybe BSL.ByteString
似乎是“对数组元素的索引遍历”,而imap
似乎是FunctorWithIndex
,那么为什么这不能像预期的那样组合呢?我错过了什么
附言:我注意到大约两年前我问了一个问题。这个问题在概念上是相同的吗?我是不是对镜片缺乏一些基本的了解
在尝试了几次随机选择后,我终于得到了答案
置换。但我还是不明白为什么前者有效,但是
后者没有:
x ^.. (key "conversations") . values . (key "id") . _String
-- vs
x ^@.. (key "conversations") . values . (imap (\ _ v -> v ^? key "id"))
x ^.. (key "conversations") . values . (key "id") . _String
-- vs
x ^@.. (key "conversations") . values . (imap (\ _ v -> v ^? key "id"))
是一个映射函数,是
fmap
的变体,可访问索引。它不是光学元件,所以你不能用这种方式将它与其他光学元件组合。虽然有一个索引setter版本的imap
,但它仍然没有帮助,因为(^..)
需要折叠,而(^@..)
需要索引折叠,另一方面,设置一个遍历,该遍历可用于以您想要的方式检索特定属性,因为所有遍历都是折叠的。您能解释一下为什么imap
不能按我希望的方式组合吗?它是一种“常规”功能,即与镜头无关吗?@SaurabhNanda是的,部分问题在于imap
没有正确的类型。有一个索引setter版本的imap
,imap
(即imap
映射到普通fmap
),但它仍然不能做您想要的事情。setter只能修改目标,不能检索它们。因为您正试图使用(^..)
检索元素,所以setter不会有帮助:您需要折叠<代码>键“id”是一个遍历,每个遍历都是一个折叠,因此它可以正常工作。