scala - 为什么 Scala 不能从隐含证据中推断出类型

标签 scala type-inference

我试过了,但失败了,错误:缺少扩展函数的参数类型 ((x$29) => x$29.sum)

有人可以解释为什么会这样吗?难道只是因为 Scala 的类型推断不够强大?

object HelloStackOverflow {
    implicit class Repro[T](val iterable: Iterable[T]) extends AnyVal {
        def foo[A, B, Z](bar: Iterable[B] => Z)(implicit evidence: T <:< (A, B)) =
            bar(iterable.map(_._2))
    }

    List(("a", 1), ("b", 2)).foo(_.sum)
}

(使用 Scala 2.10)

最佳答案

这是因为“必须完全知道匿名函数的参数类型”(Scala 语言规范 8.5)。

当一个方法采用匿名函数时,scala 使用它知道参数类型的事实让调用者省略匿名函数参数的类型(让你写类似 x => x+1 而不是 x: Int => x+1 ,或 _.sum 而不是 x: Iterable[Int] => x.sum 。这是 scala 中推理的一个很好的应用程序。但显然,这首先需要知道匿名函数的确切预期类型,这里不是这种情况:匿名函数 bar 的参数是 Iterable[B] 类型。B 是一个自由类型变量,不能以任何方式从先前的参数列表中推断出来(方法中没有先前的参数列表foo)。 所以根本不可能 B 的类型在匿名函数中 (_.sum)可以推断,这会触发错误,因为知道确切的类型是规范规定的。

这很合乎逻辑。在 scala 中,匿名函数只是(像任何函数一样)一个对象。创建匿名函数意味着实例化一个通用类(扩展 Function* ),其中函数参数的类型被编码为 Function* 的类型参数。类(再读一遍,我保证这句话是有道理的)。如果不完全指定类型参数,就不可能实例化任何泛型类。函数也不异常(exception)。

正如 Impredicative 在评论中显示的那样,显式指定匿名函数参数的类型可以修复编译错误:

List(("a", 1), ("b", 2)).foo((a : Iterable[Int]) => a.sum)

甚至:

List(("a", 1), ("b", 2)).foo((_.sum):Iterable[Int] => Int)

但在您的情况下,无需显式指定匿名函数的类型即可解决问题:

object HelloStackOverflow {
    implicit class Repro[A,B](val iterable: Iterable[(A,B)]) extends AnyVal {
        def foo[Z](bar: Iterable[B] => Z) =
            bar(iterable.map(_._2))
    }

    List(("a", 1), ("b", 2)).foo(_.sum) // works like a charm
}

也许是你使用单一类型参数的原因 T (而不是我上面示例中的参数 AB),并有证据表明 T <: (A, B)是在你的真实代码中你在类 Repro 中有其他方法吗?不需要 T成为一对。在这种情况下,只需创建另一个隐式类 Repro2T类型参数,并将这些其他方法迁移到那里。您不需要将所有的扩充内容放在同一个隐式类中。

关于scala - 为什么 Scala 不能从隐含证据中推断出类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15093071/

相关文章:

java - takeWhile, dropWhile 惰性 java9

scala - 尝试实现 `Absurd` 类型类时的隐式错误

java - 在 JScrollPane 中显示 JLayeredPane

scala - 折叠左单行中的类型推断?

Ocaml 类型推断不正确

scala - 如何在 Scala 中使用 Tapir 创建具有多个模式的端点

java - Play 2.2.1 Java : Whats the equivalent of @before filters from play 1. X?

javascript - 显式类型传递是否不等同于类型推断(就表达能力而言)?

Scala:如何定义 "generic"函数参数?

c# - 尽管 intellisense 列出了定义,但找不到定义?