使用 2.13 进行了测试,但我认为自 2.12 以来一直都是这样,而且我之前没有遇到过此类问题:
trait Extractor[-X, +Y] {
def optional :X => Option[Y] = apply
def apply(x :X) :Option[Y]
def andThen[Z](extractor :Extractor[Y, Z]) :Extractor[X, Z] = {
val first = optional; val second = extractor.optional
Extractor { x :X => first(x).flatMap(second) }
}
def andThen[Z](req :Y => Z) :Extractor[X, Z] = {
val first = optional
Extractor { x :X => first(x).map(req) }
}
def compose[W](extractor :Extractor[W, X]) :Extractor[W, Y] = extractor andThen this
def compose[W](req :W => X) :Extractor[W, Y] = Extractor(req andThen optional)
}
Scalac 对第一个 compose
的实现有一个隐晦的提示:
Error:(44, 31) type mismatch;
found : net.noresttherein.oldsql.morsels.Extractor[X,Y]
required: W => ?
def compose[W](extractor :Extractor[W, X]) :Extractor[W, Y] = extractor andThen this
注释掉采用函数的 andThen
变体可以解决该问题。
将代码更改为 extractor.andThen[Y](this)
也是如此(显式类型参数是这里的关键)。
我的猜测是,不知何故我的 SAM 类型被提升为函数,但我无法猜测为什么它会优先于方法。正如我在这里提供的两个“解决方案”,我并不是在寻找解决方法,而是在了解正在发生的情况。这是多年来我第一次不明白发生了什么,并希望将来消除类似的问题。
最佳答案
您可能违反了 overloading resolution 的新规则,旨在协助类型推断。
问题是 extractor.andThen(this)
中 arg 的“预期类型”是什么。
“高阶函数参数类型推断的直觉是所有参数都必须是类似函数的类型。”
因此,删除 apply
方法会破坏该条件并让输入继续进行。
规范补充道:“目的不是引导重载解决方案。”
它应该是:“目的不是破坏重载决策。”
我猜是好意铺垫many roads .
编辑:它在 2.12 中有效,无需修改规则。在旧系统下,如果方法重载,就没有预期的类型。
值得补充的是,它可能符合回归的条件。例如,他们可以根据之前的规则进行后备类型检查。
这是一个ticket为了它。
关于scala - 为什么 scalac 在重载 'andThen' 时会对未实现 Function 的 SAM 类型感到困惑?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60677577/