如何使用lens折叠XML元素的节点?
我正在使用包来处理XML 给定一个,我想在它的如何使用lens折叠XML元素的节点?,xml,haskell,haskell-lens,Xml,Haskell,Haskell Lens,我正在使用包来处理XML 给定一个,我想在它的elementNode::[Node]字段上执行类似于concatMap的计算。具体来说,满足某些条件的NodeElement应该生成更多的NodeElements,而所有其他情况(其余的NodeElements和其他Node构造函数)都应该生成一个单例列表。然后,它应该连接到[Node]中,并用作覆盖给定元素的当前元素Node的值 我正在努力写合适的镜头咒语来做到这一点。以下是我到目前为止的想法: over nodes $ concatMapOf
elementNode::[Node]
字段上执行类似于concatMap
的计算。具体来说,满足某些条件的NodeElement
应该生成更多的NodeElement
s,而所有其他情况(其余的NodeElement
s和其他Node
构造函数)都应该生成一个单例列表。然后,它应该连接到[Node]
中,并用作覆盖给定元素的当前元素Node
的值
我正在努力写合适的镜头咒语来做到这一点。以下是我到目前为止的想法:
over nodes $ concatMapOf someLensMagic (myFun :: Element -> [Node])
它会进行类型检查,但我无法实现someLensMagic
。非常感谢您的帮助。如果myFun
解释了如何使用NodeElement
构造函数,并且您希望为其他节点
构造函数创建一个空列表,您可以使用concatMapOf\u元素
要为其他构造函数提供单例列表,您应该修改myFun
以处理Node
的所有构造函数。然后您可以使用concatmapmyfun
,而不是concatMapOf
。(在本例中,您可以使用concatMapOf traverse myFun
,但这更难理解。)
无法编写将生成单例列表的someLensMagic
,因为无法从NodeComment
中提取元素.在折叠中以不同方式处理某些子节点的一种方法,它用于根据条件将它们放置在任一
的不同分支中,然后使用一个函数,该函数允许您对任一
的每个分支应用不同的遍历
例如,此函数应返回元素
的子节点
,其特殊性是,对于满足条件的节点,将返回其子节点:
foldDifferently :: (Node -> Bool) -> Fold Element Node
foldDifferently p =
nodes
. folded
. to (\n -> if p n then Right n else Left n)
. beside id (_Element . nodes . folded)
我已经完成了两个连续的concatMap
s:
over nodes (concatMap $ concatMapOf _Element myFun) element
这是次优的解决方案,因此我不会将其标记为答案,并欢迎任何其他建议。最严格的解决方案是,在myFun
周围编写一个包装器,以便它可以处理节点
而不是元素
s:
myFun'::Node->[Node]
myFun'n=案例n
NodeElement el->myFun el
_->[n]
myFun'
然后可以与普通的concatMap
(与concatMapOf
)一起使用,以修改节点
字段:
over节点(concatMap myFun')
碰巧,有一种镜头魔术可以作为书写包装的替代方法。组合器将一个棱镜变成一个瞄准函数的透镜,使我们实际上可以编辑函数在特定情况下的功能。实际上,它看起来是这样的:
节点上的(concatMap$set(在_元素之外)myFun(:[]))
concatMap
的参数是一个类似于(:[])
的函数,除非该参数与\u元素
匹配,在这种情况下,它在基础元素上变为myFun
。也就是说,本质上是抽象的模式匹配。为了让大家明白这一点,我们可以尝试使用outside
模仿上面的myFun'
的定义风格:
myFun'::Node->[Node]
myFun'
=外部_元素~myFun
$\n->[n]
我真的不想从NodeComment
中提取元素。我只想让它保持原样。