0

以下表达的意图有何不同?我很惊讶他们实际上在下面的示例中键入检查并产生不同的结果。

(./) ::
  Plated a =>
  Traversal s t a a -> Traversal a a u v -> Traversal s t u v
        -- Defined in âText.XML.Lensâ
infixr 9 ./

(.) :: (b -> c) -> (a -> b) -> a -> c   -- Defined in âGHC.Baseâ
infixr 9 .

以及它们如何使用典型的 pom.xml 文件:

*Main> x ^.. root ./ ell "version" . text
["1.0-SNAPSHOT"]
*Main> x ^.. root ./ ell "version" ./ text
[]

在哪里

text ::
  Control.Applicative.Applicative f =>
  (Data.Text.Internal.Text -> f Data.Text.Internal.Text)
  -> Element -> f Element
        -- Defined in âText.XML.Lensâ

data Element
  = Element {elementName :: Name,
             elementAttributes :: containers-0.5.5.1:Data.Map.Base.Map
                                    Name Data.Text.Internal.Text,
             elementNodes :: [Node]}
        -- Defined in âText.XMLâ
instance Plated Element -- Defined in âText.XML.Lensâ
4

1 回答 1

2

(./)是基于一个Plated实例,它是具有相同类型的“孩子”的类型的类。HTML 元素、用于数学表达式的 AST 等。

这里(.)只是链遍历。所以

*Main> x ^.. root ./ ell "version" . text
["1.0-SNAPSHOT"]

转到具有本地名称 == "version" 的根节点的所有子节点,并收集其中的文本内容。(这里只有一个这样的节点)

(./)但是增加了一个额外的步骤。

*Main> x ^.. root ./ ell "version" ./ text
[]

这将转到具有本地名称 == "version" 的根节点的任何子节点,然后关注这些节点的所有子节点并选择其中的文本内容。如果没有找到子项,则生成的遍历很可能不会指向任何结果,这可能就是您得到空列表的原因。

基本上,l ./ l'遍历由 描述的内容l,产生多个目标,然后将焦点从每个目标切换到它们的“相同类型的子代”(如Plated实例所述),然后再用 遍历这些目标l'

请注意,您必须./在 root 之后使用,因为您想下降到根节点的所有直接子节点,只选择具有您感兴趣的名称的子节点。但是当查看"version"元素的内容时,你只需要它们里面的直接内容,不需要进一步遍历子元素,因此有必要使用(.)而不是(./).

于 2014-11-28T16:55:12.287 回答