【问题标题】:Why does this function overload produce a compile error in Scala?为什么这个函数重载会在 Scala 中产生编译错误?
【发布时间】:2015-11-24 12:18:59
【问题描述】:

是什么导致以下代码在 Scala 2.11 中产生编译错误?

class Foo {
  def fn(a: Seq[Int], b: Int => Int) {}

  // Comment this line out
  def fn(a: Map[String, String], c: String => Double) {}
}

object Bar {
  def main(args: Array[String]) {
    val f = new Foo()
    f.fn(Seq(1, 2), _ * 2)
  }
}

错误:

Error:(9, 21) missing parameter type for expanded function ((x$1) => x$1.$times(2))
    f.fn(Seq(1, 2), _ * 2)
                    ^

但如果 fnMap[String, String], String => Double 版本被注释掉,代码仍然可以编译。我可以通过给编译器一两个提示来轻松解决这个问题,但我从不喜欢在 Scala 中显式指定类型:-)

(旁白:我知道method overloading is frowned on in Scala

【问题讨论】:

  • 很遗憾听到您从不喜欢指定类型。这极大地影响了可读性
  • @Odomontois 这值得商榷 - Haskell 是完全推断出来的,而且 IMO 的可读性也不差。
  • @dcastro 虽然在 Haskell 中指定类型也是不错的行为。
  • @dcastro 根据我的经验并没有完全推断出来,至少在具有单态限制的 GHC 中
  • 重载和类型推断是天敌。

标签: scala overloading


【解决方案1】:

您正在为编译器创建某种“鸡与蛋”问题:

  1. 要选择重载,编译器需要知道所有参数的完整类型。
  2. 要在调用中获取函数参数的完整类型,编译器需要推断其参数的类型。
  3. 然而,要推断此参数的类型,它需要回到 1. 并选择一个重载(* 的右侧不足以进行类型推断,因为 * 本身可能会被重载)。

编译器无法跳出这个圈子,因此退出。您必须向编译器展示大门:

  • 如果您指定 lambda 参数的类型,您将解决 2. 并使编译器能够推断函数的正确类型,从而选择正确的重载。
  • 如果您使用 curried 函数(如另一个答案中所建议的那样),您可以解决 1. 并帮助编译器根据第一个参数选择适当的重载,以便随后推断第二个参数的类型。

【讨论】:

  • 重点似乎是(1)。看起来编译器应该可以选择第一个fn定义,因为第一个参数的类型是Seq[Int],但重点是不排除你希望它强制Seq[Int]成为Map[String, String]。为什么不能排除强制?
  • @expz 我想它可以,但正如所说,它使用完整的签名来解决重载。它不能像在这种情况下那样使用部分签名来解决重载,即使在这种特殊的特殊情况下,部分签名明确地标识了重载。
【解决方案2】:

我认为编译器无法确定选择哪个重载,因为函数的类型没有完全指定。协助 scala 编译器进行类型推断的一种常见方法是使用多个参数块,例如:

class Foo {
  def fn(a: Seq[Int])(b: Int => Int) {}
  def fn(a: Map[String, String])(c: String => Double) {}
}

object Bar extends App {
  val f = new Foo()
  f.fn(Seq(1, 2))(_ * 2) // this works because the overload is chosen based on the first parameter list
}

如果您不想这样做,则必须更明确地指定函数的类型,如下所示:

f.fn(Seq(1,2), (x: Int) => x * 2)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-18
    • 2023-03-22
    • 2012-01-03
    相关资源
    最近更新 更多