Scala 2类型推理

dgiusagp  于 2022-12-26  发布在  Scala
关注(0)|答案(3)|浏览(150)
def test[T: ClassTag]: T = {
  println(classTag[T])
  null.asInstanceOf[T]
}
val x1: Int = test
val x2: Int = test[Int]

印刷品

Nothing
Int

我希望编译器能够猜出Int类型,而不需要显式地提供它(编辑:在右手侧,即,使val x1: Int = test工作)。
有没有可能的解决方法来消除显式类型注解?

ac1kyiln

ac1kyiln1#

我怀疑编译器无法在val x1: Int = test[???]中推断Int,因为这两个选项:

val x1: Int = test[Int] // returns Int

以及

val x1: Int = test[Nothing] // returns Nothing <: Int

是有效的。所以编译器只需要猜出你指的是哪个选项。
当编译器有选择的时候,它通常会从选项中选择最小的类型,目前是Nothing
Why Scala Infer the Bottom Type when the type parameter is not specified?
原则上,如果你想探索左手边的类型,你可以把test变成macro,然后它甚至可以不是泛型的。把它变成白盒意味着它可以返回一个比声明的(Any)更精确的类型,例如Int
一个二个一个一个

vltsax25

vltsax252#

实际上,这里的类型推断没有错,这里的类型推断意味着编译器应该判断出T类型参数是Int,并且从方法表达式返回的值是一个整数,这是正常工作的:

x1: Int = 0 // this is the result of your first line

您也可以尝试打印以下内容:

println(x1.getClass) // int

对于泛型类型"ClassTag[_]"的隐式解析没有达到预期的效果。它打印Nothing的原因是编译器发现对象scala.reflect.ClassTag.Nothing : ClassTag[Nothing]适合您的情况。现在关于这个新事物,在SO和互联网上有大量的内容来解释为什么会发生这种情况以及如何在不同的情况下处理它。
下面是另一段代码,用于在您的情况下区分type inferencetype erasure

def nullAs[T]: T = null.asInstanceOf[T]

val int: Int = nullAs // 0: Int

// type erasure:
case class Container[T](value: T)
implicit val charContainer: Container[Char] = Container('c')

def nullWithContainer[T](implicit container: Container[T]): T = {
  println(container)
  null.asInstanceOf[T]
}

val long: Long = nullWithContainer
// prints Container(c)
// 0L

这意味着类型推断是正确的,但是类型擦除发生了,因为在运行时,charContainer的类型是Container,而不是Container[Char]

jfgube3f

jfgube3f3#

val x1: Int = test

在这一行中,你给出的Int是值x1的类型,它将保存函数test的结果,至于TclassTag,编译器找不到任何信息,这就是为什么它返回Nothing,在这种情况下,它采用val x1: Int = test[Nothing],因此您必须始终为test指定一个类型,否则它将打印Nothing

相关问题