代码之家  ›  专栏  ›  技术社区  ›  Aleksandar Dimitrov

HXT:左因子不确定箭头?

  •  7
  • Aleksandar Dimitrov  · 技术社区  · 14 年前

    我试图接受Haskell的XML工具箱( HXT )我在某个地方碰壁,因为我似乎没有完全掌握箭头作为计算工具。

    下面是我的问题,我希望通过GHCi会议更好地说明这一点:

    > let parse p = runLA (xread >>> p) "<root><a>foo</a><b>bar</b><c>baz</c></root>"
    > :t parse
    parse :: LA XmlTree b -> [b]
    

    因此Parse是一个小的帮助函数,它将我给它的任何箭头应用到平凡的XML文档中

    <root>
      <a>foo</a>
      <b>bar</b>
      <c>baz</c>
    </root>
    

    我定义了另一个helper函数,这次是为了提取具有给定名称的节点下面的文本:

    > let extract s = getChildren >>> isElem >>> hasName s >>> getChildren >>> getText 
    > :t extract
    extract :: (ArrowXml cat) =>
       String -> cat (Data.Tree.NTree.TypeDefs.NTree XNode) String
    > parse (extract "a" &&& extract "b") -- extract two nodes' content.
    [("foo","bar")]
    

    有了这个函数的帮助,很容易使用 &&& combinator将两个不同节点的文本配对,然后将其传递给构造函数,如下所示:

    > parse (extract "a" &&& extract "b" >>^ arr (\(a,b) -> (b,a))) 
    [("bar","foo")]
    

    现在是我不明白的部分:我想离开因素! extract 电话 getChildren 在根节点上两次。相反,我只想叫它一次!所以我首先得到根节点的子节点

    > let extract' s = hasName s >>> getChildren >>> getText
    > :t extract'
    extract' :: (ArrowXml cat) => String -> cat XmlTree String
    > parse (getChildren >>> isElem >>> (extract' "a" &&& extract' "b"))
    []
    

    请注意,我已经试着重新排序了,比方说,isElem,等等,以便找出这是否是问题所在。但就目前的情况来看,我不知道为什么这不起作用。有一个箭头“教程” on the Haskell wiki 我的理解是 应该 有可能做我想做的事-即使用 &&& 为了把两次计算的结果配对。

    它也起作用,但只有在箭头链的开始,而不是中间的低谷,当我已经有了一些结果,我想保持'共享'。我有一种感觉,我只是不能把我的头围绕在一个正常的函数组合和箭头记法的想法之间的差异。我会非常感谢你的指点!(即使只是一些普通的箭头教程,比Haskell wiki上的更深入。)

    谢谢您!

    1 回复  |  直到 14 年前
        1
  •  2
  •   Travis Brown    14 年前

    如果将箭头转换为(然后从)确定性版本,则可以按预期工作:

    > let extract' s = unlistA >>> hasName s >>> getChildren >>> getText
    > parse (listA (getChildren >>> isElem) >>> (extract' "a" &&& extract' "b"))
    [("foo","bar")]
    

    不过,这不是很令人满意,我也记不清为什么 (&&&) 用一个不确定的箭头(我个人会使用 proc/do notation 任何比这更复杂的事情)。


    更新: 这里好像有点奇怪 runLA xread . 如果你使用 runX readString 一切如期而至:

    > let xml = "<root><a>foo</a><b>bar</b><c>baz</c></root>"
    > let parse p = runX (readString [] xml >>> p)
    > let extract' s = getChildren >>> hasName s >>> getChildren >>> getText
    > parse (getChildren >>> isElem >>> (extract' "a" &&& extract' "b"))
    [("foo","bar")]
    

    这意味着您必须在 IO monad,但是使用 跑道 无论如何(更好的错误消息等)。

    推荐文章