Reputation: 9771
Can't possibly read the following type return by the REPL
def returnfuncdefGen[A] = (i: A) => i.toString.length
returnfuncdefGen: [A]=> A => Int
while i do understand that
def returnfuncdefGen[A](i: A) = i.toString.length
returnfuncdefGen: [A](i: A)Int
The first version is what the author of FP simplified (scala) call coercing parameterize method into a function
How exactly does one read this [A]=> A => Int ?
Also I find the notion of coercion a bit weird. It feels to me like creating a parentheless method that return a function. Now the generic on top i can't explain other by saying that the literal function does a closure of the type defined by the method.
Overall if someone could clarify to me what is happening and how to read that type [A]=> A => Int that would really help.
Upvotes: 2
Views: 147
Reputation: 51683
If you do
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")
you'll see
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())))
That's because for NullaryMethodType
toString
was defined as =>
override def safeToString: String = "=> "+ resultType
Maybe you wanted it to be defined as ""
but that was not the case till 2.13.1 (including).
In 2.13.2 for NullaryMethodType
toString
was changed to ""
override def safeToString: String = resultType.toString
https://github.com/scala/scala/blob/2.13.x/src/reflect/scala/reflect/internal/Types.scala#L2953
So now in 2.13.2, 2.13.3 the above code prints
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())))
as you wanted.
By the way, in 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}
Upvotes: 5
Reputation: 48420
Until Scala 2.13.1, I believe the notational difference is by design as per SLS 3.3.1 Method Types
A method type is denoted internally as (Ps)𝑈 ... A special case are types of methods without any parameters. They are written here => T.
Because method returnfuncdefGen
is without any parameters, then its type is represented using => T
notation
scala> def returnfuncdefGen[A] = (i: A) => i.toString.length
def returnfuncdefGen[A] => A => Int
where T = A => Int
See Dmytro's answer for changes in Scala 2.13.2 by 11416 MethodType.toString prints in scala format #7798
Upvotes: 6
Reputation: 1868
[A] => A => Int
is a function with a type parameter of A
and no arguments which returns a function `A => Int
This is different to def returnfuncdefGen[A](i: A) = i.toString.length
which is a function with a type parameter of A
and a single argument of type A
which returns an Int
Upvotes: 3