泛型方法转换为部分应用函数时的类型推导问题

在泛型方法通过下划线方式转换为部分应用函数(偏应用函数)的时候,类型推导有一个细节。我们先看返回值是泛型(参数化)的情况:

泛型参数T会被编译器约束为 T >: Nothing <: Any,即上限是Any,下限是Nothing.

scala> def method[T]():T = null.asInstanceOf[T]
method: [T]()T

scala> val f = method _
f: () => Nothing = <function0>

如上,在只有结果类型是参数化类型的情况下,因为Function0的返回值类型声明为协变的,从里氏替换的角度,编译器进行推导时T会选用最底层的类型,这个类型是Nothing

scala> def method[T](p:T) = println("ok")
method: [T](p: T)Unit

scala> val f = method _
f: Any => Unit = <function1>

如上,在只有方法参数是参数化类型的情况下,因为Function1的参数类型声明是逆变的,从里氏替换的角度,编译器进行推导时T会选用最上层的类型,这个类型是Any

而若方法的参数和返回值都用参数化类型表示时,则类型推导选择的是都是Nothing,而非入参是 Any,返回值是Nothing 这种不一致的行为。

scala> def method[T](p:T) = p
method: [T](p: T)T

scala> val f = method _
f: Nothing => Nothing = <function1>

归根到底,是因为scala/java的方法支持泛型(具备类型参数化多态),而scala的函数却在构造时需要具体的输入和输出类型,所以在从方法转换为函数的过程时必然是有所损失的。

泛型方法转换为部分应用函数时的类型推导问题》上有3条评论

  1. bigbully_

    而若方法的参数和返回值都用参数化类型表示时,则类型推导选择的是都是Nothing,而非入参是 Any,返回值是Nothing 这种不一致的行为。

    scala> def method[T](p:T) = p
    method: [T](p: T)T

    这段应该是
    scala> def method[T](p:T):T= p
    method: [T](p: T)T

    少了个返回值吧?

    回复
    1. hongjiang 文章作者

      这种情况下返回值类型可省略,编译器的推断返回类型也肯定是T。

      回复
  2. Pingback引用通告: scala类型系统:类型推导 | 在路上

发表评论

电子邮件地址不会被公开。 必填项已用*标注