运行reduceLeft时类型不匹配

时间:2017-02-08 17:54:11

标签: scala

我有一个ConfigRule特征,其中transform方法为

trait ConfigRule {
  final def transform(doc: Node): Node = { .....}
}

然后我ConfigTransformer看起来像transform方法

trait ConfigTransformer {
    def transform(doc: Node, rules: Seq[ConfigRule]) = {
    rules.reduceLeft((x, y) => x.transform(doc).andThen(y.transform(_)))
  }
}

我尝试将其作为

运行
object Runner extends App {
  override def main(args: Array[String]): Unit = {
    val n1 = NewNodeRule(<foo/>, <bar/>, Seq.empty, "adding bar under foo")
    val n2 = NewNodeRule(<garage/>, <car/>, Seq.empty, "adding car under garage")

    ConfigTransformer.transform(<Root/>, Seq(n1, n2))
  }
}

我收到编译错误

Error:(18, 56) type mismatch;
 found   : PartialFunction[Int,scala.xml.Node]
 required: solutions.xml.ConfigRule
    rules.reduceLeft((x, y) => x.transform(doc).andThen(y.transform(_)))

我做错了什么?

2 个答案:

答案 0 :(得分:4)

我还不是Scala专家,但问题是你没有在ConfigRule语句中返回reduceLeft类型的对象(它是Node,这就是你收到错误的原因)。你想要的是我猜foldLeft。这是一个例子:

trait ConfigTransformer {
    def transform(doc: Node, rules: Seq[ConfigRule]) = {
        rules.foldLeft(doc)((d, x) => x.transform(d))
    }
}

答案 1 :(得分:2)

嗯......问题是Seq[A]的reduceLeft有以下签名,

def reduceLeft[B >: A](op: (B, A) ⇒ B): B

这意味着您的缩减功能op应该使用accumulator: BcurrentElem: A,并且应该返回B,其中Bsuper-class A reduceLeft

关于accumulator的一个重要注意事项是第一次减少,即。使用Seq的第一个和第二个元素作为参数完成Seq的第一次计算。

换句话说......只有reduceLeft中的元素才会参与foldLeft

对于您希望以其他值作为初始累加器开始的用例,您应该使用def foldLeft[B](z: B)(op: (B, A) ⇒ B): B ,其具有以下签名,

accumulator: B

请注意,它需要初始zfold此处)和B函数作为参数。另外...... foldLeft这里可以是你想要的任何类型,与A没有任何关系。这就是你的情况,

现在,如果您想使用trait ConfigTransformer { def transform(doc: Node, rules: Seq[ConfigRule]) = rules.foldLeft(doc)((acc, elem) => elem.transform(acc)) }

执行此操作
getTransportInfo