当前位置:  开发笔记 > 编程语言 > 正文

scala中奇怪的类型推断

如何解决《scala中奇怪的类型推断》经验,为你挑选了1个好方法。

我对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作为IDE与Scala 2.11.6

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

顺便说一句我刚注意到当我在'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) => ()

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



1> mikołak..:
原始编译错误

发生编译错误,因为此函数:

(a: Any) => Unit

是类型的

Any => Unit.type

不是类型:

Any => Unit

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

你需要的是实际返回一个类型的值Unit.正如文档中所述,唯一的这样的价值是().

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


编辑:关于补充问题.

转换为单位

这里:

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

您明确键入表达式以使其返回类型为Unit.通常它会导致类型错误,但(正如您所怀疑的)"幸运的是" 您触发了一个预定义的隐式值转换,具体来说:

价值丢弃

如果e具有某种值类型且期望的类型是Unit,则通过将e嵌入到术语{e;中来将e转换为期望的类型.()}.

所以这:

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

变为:

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

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

推荐阅读
殉情放开那只小兔子
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有