HXT:左因子非确定性箭头?

问题描述 投票:0回答:1

我试图接受 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>

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

> 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")]

借助此函数,可以轻松使用

&&&
组合器将两个不同节点的文本配对,然后将其传递给构造函数,如下所示:

> 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 等的调用,以查明这是否是问题所在。但就目前情况而言,我只是不知道为什么这不起作用。 Haskell wiki 上有一个箭头“教程”,按照我的理解,它应该可以做我想做的事情——即使用 &&&

 来将两个结果配对计算。

它也确实有效——但仅限于箭头链的开始,而不是中途波谷,当我已经有了一些结果时,我想保持“共享”。我有一种感觉,我无法理解正常函数组合和箭头表示法之间的想法差异。我将非常感谢任何指点! (即使只是一些比 Haskell-wiki 上的更深入的通用箭头教程。)

谢谢!

haskell hxt arrow-abstraction
1个回答
2
投票
如果将箭头转换为(然后从)确定性版本,则这将按预期工作:

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

不过,这并不是很令人满意,而且我一时记不起为什么

(&&&)

 会以这种方式使用非确定性箭头(我个人会使用 
proc/do
 表示法
)比这复杂)。


更新: 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 中运行解析器,但无论如何使用 
runX
 都有优点(更好的错误消息等)。

© www.soinside.com 2019 - 2024. All rights reserved.