scala - 为什么 scalac 在重载 'andThen' 时会对未实现 Function 的 SAM 类型感到困惑?

标签 scala single-abstract-method

使用 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/

相关文章:

scala - 定义 ADT 时案例对象 T 和案例类 T() 之间的差异?

scala - 含糊不清的过载,即使是更具体的

scala - SAM 和匿名函数的区别

scala - 防止 Scala 特征成为 SAM 类型

function - 如何在 Scala 中使 lambda 函数通用?

scala - 多态Scala返回类型

python - 将基于 python-twisted 的代码移植到 scala : framework advice needed

Scala 尾递归