【问题标题】:Weird type inference in scalascala中的奇怪类型推断
【发布时间】:2015-12-07 10:42:27
【问题描述】:

我在 Scala 类型推断方面遇到了一些问题。 在下面的工作表示例中,我定义了一个 Map,它将 Any 值映射到返回 Unit 值的函数。

有趣的是,当我尝试仅使用一行代码定义同一个映射时,它不起作用,因为“bar”函数的返回类型突然变为 Any 而不是 Unit。

type UnitFun = (Any) => Unit

val foo = "foo"
val bar = (a: Any) => System.out.println("bar")

val map: Map[Any, UnitFun] = Map().withDefaultValue(((a: Any) => Unit))
val doesCompile: Map[Any, UnitFun] = map + (foo -> bar)

val doesNotCompile: Map[Any, UnitFun] = Map().withDefaultValue(((a: Any) => Unit)) + (foo -> bar)

我将 IDEA14 用作 Scala 2.11.6 的 IDE

在我看来这是 Scala 编译器的功能/错误,还是我遗漏了什么?

顺便说一句,我刚刚注意到,当我像这样在 'doesNotCompile' 中使用 'bar' 作为默认值时:

val doesCompileNow: Map[Any, UnitFun] = Map().withDefaultValue(bar) + (foo -> bar)

它似乎突然起作用了,我现在很困惑。 :D

编辑 1: @Mikolak

在这种情况下,下面的代码是如何工作的? :)

val a: Any => Unit = (a: Any) => Unit
val b: Any => Unit = (a: Any) => ()

两个表达式不应该是不同的类型吗?还是涉及到一些隐式类型转换?

【问题讨论】:

  • 添加了有关您的编辑的说明。请注意,这是一种与原始现象完全正交的现象。
  • 已经看过了,我认为从 Unit.typeAny 的隐式转换(根据 intellij 输出)是让我偏离轨道的原因这个。我认为这只是另一个隐式转换。 :)
  • 接下来要补充一点:不信任 IntelliJ 的语法检查。虽然慢慢变得更好,但它仍然有输出误报和漏报的倾向。换句话说,当你遇到一个奇怪的错误时,你的第一个行动应该是运行sbt compile
  • 我现在知道我使用 'Unit' 而不是 '()' 犯了一个错误,但有趣的是,根据我编写代码的方式,这些隐式转换会导致不同的类型(第一段代码)。 ^^
  • 是的,当语言的输入既强大又不显眼时,这就是要付出的代价——在这样的极端情况下,你一定会得到看似不直观的结果。

标签: scala dictionary type-inference


【解决方案1】:

原来的编译错误

编译错误是因为这个函数:

(a: Any) => Unit

属于类型

Any => Unit.type

并且不是的类型:

Any => Unit

换句话说,您将返回Unit,即Unit 类型的伴随对象。该伴生对象的类型为Unit.type,与Unit 的类型不同(这适用于Scala 中的所有伴生对象)。

您需要实际返回一个Unit 类型的值。 As outlined in the docs唯一这样的值是()

所以,你的默认函数应该是:(a: Any) => ()


编辑:关于补充问题。

单位换算

这里:

val a: Any => Unit = (a: Any) => Unit

您正在显式键入表达式以使其返回类型为Unit。通常它会导致类型错误,但是(正如您所怀疑的)“幸运”您触发了one of the pre-defined implicit value conversions,具体来说:

价值丢弃

如果 e 具有某个值类型并且预期类型是 Unit,则通过将 e 嵌入到术语 { e; 中将 e 转换为预期类型() }。

所以,这个:

(a: Any) => Unit  //return type is Unit.type

变成:

(a: Any) => {Unit; ();} //return type is Unit

请注意,根据定义,转换适用于任何值,例如val c: Unit = "c" 产生相同的结果。

【讨论】:

    猜你喜欢
    • 2019-04-27
    • 2016-02-29
    • 1970-01-01
    • 2020-08-12
    • 1970-01-01
    • 1970-01-01
    • 2012-11-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多