如何使用Endomorphic包装器修复此练习?

时间:2015-07-14 08:16:54

标签: xml scalaz kleisli

这是我之前question的后续内容。

假设我需要按路径查找XML节点。我可以编写一个函数来按名称获取子节点

import scala.xml.{Node => XmlNode}

def child(name: String): XmlNode = Option[XmlNode] = _.child.find(_.label == name)

我用kleisli撰写child函数; e.g。

   
scala> val a = <a><a0><a1><a2/></a1></a0></a>
a: scala.xml.Elem = <a><a0><a1><a2/></a1></a0></a>

scala> val find01 = Kleisli(child("a0")) >=> Kleisli(child("a1"))
findAB: scalaz.Kleisli[Option,scala.xml.Node,scala.xml.Node] = Kleisli(<function1>)

scala> find01(a)
res85: Option[scala.xml.Node] = Some(<a1><a2/></a1>)

现在我正在使用endomorphic包装器,但它不起作用:

 scala> List(child("a0"), child("a1")).foldMap(Endomorphic.endoKleisli[Option, XmlNode])
 res93: scalaz.Endomorphic[[α, β]scalaz.Kleisli[Option,α,β],scala.xml.Node] = Endomorphic(Kleisli(<function1>))

 scala> res93.run(a)
 res94: Option[scala.xml.Node] = None

你能帮忙找到错误吗?

1 个答案:

答案 0 :(得分:2)

在第一个示例中,您是从左到右(>=>)撰写。

Endomorphic calls the compose method(a.k.a。<=<),从右到左工作。

因此,您的第二个示例首先捕获<a1>,然后在其中查找<a0>,这显然会失败。

有两种方法可以恢复从左到右的行为。您可以在折叠之前反转列表,或将每个元素包装在Dual