【问题标题】:Scala missing parameter type for expanded functionScala缺少扩展函数的参数类型
【发布时间】:2016-07-27 10:59:32
【问题描述】:

以下代码无法编译:

def f[T](conv: Option[String => T]) {}
f(Some(_.toInt))

<console>:13: error: missing parameter type for expanded function ((x$1) => x$1.toInt)

当然,显式类型就可以了:

scala> f(Some((x: String) => x.toInt))

为什么编译器不能在这里推断字符串类型?有什么歧义吗?

一般来说,是否可以通过下划线扩展手动检查和检查生成的代码?

【问题讨论】:

  • @slouc,把它作为一个 asnwer 发布 - 这是一个正确的。如果 OP 创建了一些涉及与 String 相关的一些变化或继承的类型类,那么它可能在某些情况下能够推断它,但否则你可以只传递一些 ClassWithoutToInt 并且它不能用下划线推断它,跨度>
  • @sebszyller 我刚刚删除了我的评论,因为我认为它是错误的 :) 你如何解释如果它不是用于选项的事实,也就是说,如果方法只采用函数字符串=> T,你可以通过 f(_.toInt) 并且它会工作吗?
  • @slouc 我不知道你的答案是什么,但希望我能解释为什么它会起作用。
  • SO 抱怨没有提出足够多的问题。我同意按照共同的直觉,这应该可行。当然,我可能有充分的理由错了。
  • 在 REPL 中使用 f(_.toInt) // show-Xprint:typer 来查看 typer 如何查看您的代码。

标签: scala


【解决方案1】:

基本问题(我相信)是,当键入Some(_.toInt) 时,编译器需要推断Some.apply[A](x: A) 的类型参数,为此,它首先需要对参数进行类型检查。因此,_.toInt 使用 A(被视为未知类型常量)作为预期类型进行类型检查。这会失败,因为只有在预期类型是函数类型(或从 Scala 2.12 开始,单一抽象方法类型)时,才允许匿名函数不指定参数类型。然后编译器再次尝试使用undefined 作为预期类型,但由于同样的原因失败。

在这种情况下,预期的返回类型实际上足以确定类型参数,然后这将允许对 _.toInt 进行类型检查,但这不是它的设计工作方式。

如果需要,血淋淋的细节在 http://scala-lang.org/files/archive/spec/2.11/06-expressions.html 第 6.6、6.23 和 6.26.4 段中。

【讨论】:

  • 这是 slouc 的原始答案,扩展了 apply 附加组件。它是正确的,imo。
  • 匿名函数只允许在由期望类型给出时不指定参数类型。“当它们由期望类型给出时”是什么意思?跨度>
  • 是的,无论如何,这是一个更彻底的解释。我更多的是一种预感。谢谢阿列克谢
  • 不是 6.26.4 方面的专家,但对我来说,匿名乐趣不能为约束提供 var 并不明显:Some[b](_.toInt) <: Option[String => a]Some[b](c => Int) <: Option[String => undefined]。 args 使用预期类型进行类型检查(但类型参数固定)。因此,我们的直觉认为这只是一个限制。
  • 所以,要恢复全貌,会发生以下情况: 1) 编译器看到f() 并尝试确定它的类型,但它还不知道; 2) 为此,它继续查看Some 并尝试确定它的类型; 3) 为此,它继续前进并看到_.toInt。为了推断_ 的类型,编译器需要知道f 的类型,这仍然是未知的。 4)我们有一个僵局。我说对了吗?请注意,明确指定 f 的类型有效:f[Int](Some(_.toInt))。正如 Yuval 所问的,我还希望看到有关“何时按预期类型给出”的详细说明。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-04-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-29
  • 1970-01-01
  • 2017-12-12
相关资源
最近更新 更多