gpt4 book ai didi

scala - 为什么 Scala 类型推断在这里失败?

转载 作者:行者123 更新时间:2023-12-04 01:53:09 24 4
gpt4 key购买 nike

我有 this class在斯卡拉:

object Util {
class Tapper[A](tapMe: A) {
def tap(f: A => Unit): A = {
f(tapMe)
tapMe
}

def tap(fs: (A => Unit)*): A = {
fs.foreach(_(tapMe))
tapMe
}
}

implicit def tapper[A](toTap: A): Tapper[A] = new Tapper(toTap)
}

现在,
"aaa".tap(_.trim)

不编译,给出错误

error: missing parameter type for expanded function ((x$1) => x$1.trim)



为什么类型不推断为 String ?从错误看来,隐式转换确实触发了(否则错误将沿着“ tap 不是类 String 的成员”)。似乎转换必须是 Tapper[String] ,这意味着参数的类型是 String => Unit (或 (String => Unit)*)。

有趣的是,如果我注释掉 tap 中的任何一个定义,然后它确实编译。

最佳答案

6.26.3 Overloading Resolution

One first determines the set of functions that is potentially applicable based on the shape of the arguments

...

If there is precisely one alternative in B, that alternative is chosen.

Otherwise, let S1, . . . , Sm be the vector of types obtained by typing each argument with an undefined expected type.


tap 的两个重载是潜在适用的(基于参数的“形状”,这说明了 arity 和类型构造函数 FunctionN)。

因此,打字机继续进行:
val x = _.trim

并失败。

更智能的算法可以采用每个备选方案的相应参数类型的最小上限,并将其用作预期类型。但这种复杂性并不值得,IMO。重载有许多极端情况,这只是另一种情况。

但是在这种情况下,如果您确实需要接受单个参数的重载,则可以使用一个技巧:
object Util {
class Tapper[A](tapMe: A) {
def tap(f: A => Unit): A = {
f(tapMe)
tapMe
}

def tap(f0: A => Unit, f1: A => Unit, fs: (A => Unit)*): A = {
(Seq(f0, f1) ++ fs).foreach(_(tapMe))
tapMe
}
}

implicit def tapper[A](toTap: A): Tapper[A] = new Tapper(toTap)

"".tap(_.toString)
"".tap(_.toString, _.toString)
"".tap(_.toString, _.toString, _.toString)
}

关于scala - 为什么 Scala 类型推断在这里失败?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3315752/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com