将参数化方法强制转换为函数时,Scala 奇怪的类型?

Maa*_*mon 2 methods scala

无法读取 REPL 返回的以下类型

def  returnfuncdefGen[A] = (i: A) => i.toString.length

returnfuncdefGen: [A]=> A => Int
Run Code Online (Sandbox Code Playgroud)

虽然我明白

def  returnfuncdefGen[A](i: A) = i.toString.length

returnfuncdefGen: [A](i: A)Int
Run Code Online (Sandbox Code Playgroud)

第一个版本是FP的作者简化(scala)调用coercing parameterize方法到函数中

人们究竟如何阅读这个[A]=> A => Int

我也觉得强制的概念有点奇怪。对我来说,这就像创建一个返回函数的无括号方法。现在顶部的泛型我无法通过说文字​​函数执行方法定义的类型的闭包来解释其他。

总的来说,如果有人可以向我澄清正在发生的事情以及如何阅读该类型 [A]=> A => Int,那真的会有所帮助。

Mar*_*lic 6

在 Scala 2.13.1 之前,我相信符号差异是根据SLS 3.3.1 方法类型设计的

方法类型在内部表示为 (Ps) ...一种特殊情况是没有任何参数的方法类型。他们写在这里=> T。

因为方法returnfuncdefGen没有任何参数,所以它的类型用=> T符号表示

scala> def  returnfuncdefGen[A] = (i: A) => i.toString.length
def returnfuncdefGen[A] => A => Int
Run Code Online (Sandbox Code Playgroud)

在哪里 T = A => Int

有关 Scala 2.13.2 by 11416 MethodType.toString 以 Scala 格式打印的更改,请参阅 Dmytro 的答案#7798

  • @DmytroMitin Dotty 似乎仍然以旧的方式打印它。 (2认同)

Dmy*_*tin 5

如果你这样做

object App {
  def returnfuncdefGen[A] = (i: A) => i.toString.length
  def returnfuncdefGen1[A]() = (i: A) => i.toString.length
  def returnfuncdefGen2[A](i: A) = i.toString.length
}

def printSignature(name: String): Unit = {
  import scala.reflect.runtime.universe._
  val t = typeOf[App.type].decl(TermName(name)).typeSignature
  println(s"t=$t, showRaw(t)=${showRaw(t)}")
}

printSignature("returnfuncdefGen")
printSignature("returnfuncdefGen1")
printSignature("returnfuncdefGen2")
Run Code Online (Sandbox Code Playgroud)

你会看到的

t=[A]=> A => Int, showRaw(t)=PolyType(List(TypeName("A")), NullaryMethodType(TypeRef(ThisType(scala), scala.Function1, List(TypeRef(NoPrefix, TypeName("A"), List()), TypeRef(ThisType(scala), scala.Int, List())))))
t=[A]()A => Int, showRaw(t)=PolyType(List(TypeName("A")), MethodType(List(), TypeRef(ThisType(scala), scala.Function1, List(TypeRef(NoPrefix, TypeName("A"), List()), TypeRef(ThisType(scala), scala.Int, List())))))
t=[A](i: A)Int, showRaw(t)=PolyType(List(TypeName("A")), MethodType(List(TermName("i")), TypeRef(ThisType(scala), scala.Int, List())))
Run Code Online (Sandbox Code Playgroud)

那是因为 forNullaryMethodType toString被定义为=>

override def safeToString: String = "=> "+ resultType
Run Code Online (Sandbox Code Playgroud)

也许您希望将其定义为""但直到 2.13.1(包括)才如此。

在 2.13.2 forNullaryMethodType toString改为""

override def safeToString: String = resultType.toString
Run Code Online (Sandbox Code Playgroud)

https://github.com/scala/scala/blob/2.13.x/src/reflect/scala/reflect/internal/Types.scala#L2953

所以现在在 2.13.2, 2.13.3 上面的代码打印

t=[A]A => Int, showRaw(t)=PolyType(List(TypeName("A")), NullaryMethodType(TypeRef(ThisType(scala), scala.Function1, List(TypeRef(NoPrefix, TypeName("A"), List()), TypeRef(ThisType(scala), scala.Int, List())))))
t=[A](): A => Int, showRaw(t)=PolyType(List(TypeName("A")), MethodType(List(), TypeRef(ThisType(scala), scala.Function1, List(TypeRef(NoPrefix, TypeName("A"), List()), TypeRef(ThisType(scala), scala.Int, List())))))
t=[A](i: A): Int, showRaw(t)=PolyType(List(TypeName("A")), MethodType(List(TermName("i")), TypeRef(ThisType(scala), scala.Int, List())))
Run Code Online (Sandbox Code Playgroud)

如你所愿。

顺便说一句,在 Dotty 0.26.0-bin-20200703-2dd1c93-NIGHTLY

def returnfuncdefGen[A] = (i: A) => i.toString.length
def returnfuncdefGen1[A]() = (i: A) => i.toString.length
def returnfuncdefGen2[A](i: A) = i.toString.length
def returnfuncdefGen3 = [A] => (i: A) => i.toString.length
def returnfuncdefGen4() = [A] => (i: A) => i.toString.length

>....def returnfuncdefGen[A] => A => Int
>....def returnfuncdefGen1[A](): A => Int
>....def returnfuncdefGen2[A](i: A): Int
>....def returnfuncdefGen3: PolyFunction{apply: [A](i: A): Int}
>....def returnfuncdefGen4(): PolyFunction{apply: [A](i: A): Int}
Run Code Online (Sandbox Code Playgroud)