3

问题:

关于隐式类的一些东西,使 reduce() 感到困惑。在隐式类中时,编译器会抱怨 reduce() 第二个参数。但是当相同的代码在非隐式方法中时,它可以编译并正常工作。

我对隐式类缺少什么?

代码:

object ImpliCurri {
    implicit class MySeq[Int](val l: Seq[Int]) {
        //not compiling
        final def mapSum(f:Int=>Int):Int = {
            l.map(x=>f(x)).reduce(_+_)
       //compile error on reduce: Type mismatch. Expected String, fount Int
        }
    }

    // works fine
    def mySum(l:Seq[Int], f:Int=>Int):Int = {
        l.map(x=>f(x)).reduce(_+_)
        // compiles and works no issues
    }
}
4

3 回答 3

5

您需要摆脱类型参数IntInt在隐式类的情况下,它实际上不是类型Int,而是一个自由类型参数,它隐藏了Int.

神秘的编译器错误的原因是编译器Any从 lambda推断类型_ + _(因为类型参数可以是任何东西),并假设+将来自toStringon type Any。如果你在类声明中替换Int为 with T,你会看到错误是一样的。

这将起作用:

implicit class MySeq(val l: Seq[Int]) {
    final def mapSum(f: Int => Int): Int = {
        l.map(x => f(x)).reduce(_ + _)
    }
 }
于 2015-01-21T01:17:33.597 回答
3

它实际上与隐式没有任何关系。如果它只是一个常规的,你会得到同样的错误class

原因是您已经声明了一个泛型类型:MySeq[Int]恰好被调用Int。所以当你说f: Int => Int你认为“哦,那是一个整数”并且编译器认为,“哦,这意味着你可以在那里填写任何类型!”。(替换你所有的Ints ,A它的工作原理是一样的。)

现在编译器处于绑定状态。您+可以将什么应用于任何一对类型?好吧,您可以将任何内容转换为 a String,并+在 a 上定义String。因此,当编译器意识到这种方法行不通时,您会收到一条非常具有误导性的错误消息。

只需删除[Int]和所有你Int的 s 将实际上意味着你认为他们的意思,隐式类版本会正常工作。

于 2015-01-21T01:19:51.027 回答
2

替换MySeq[Int](val l: Seq[Int])MySeq(val l: Seq[Int])

编译器消息的解释:
该部分为名为MySeq[Int]的类定义了一个抽象类型参数,它(自动)是一个子类并隐藏了实际的. 然后编译器尝试调用. 它看到一个隐式类的声明,它有一个带有签名的方法,所以编译器认为第二个参数应该是 a 。MySeqIntAnyscala.Int+Anyscala.Predef.any2stringadddef +(other: String): String+String

于 2015-01-21T01:17:22.353 回答