FunctionN's toString should show the Types


#1
  val intFunction:Function2[Int,Int,Int] = new Function2[Int,Int,Int] {
    override def apply(v1: Int, v2: Int): Int = v1 + v2
  }
  println(intFunction.toString())

It give me

<function2>

I think it should be better if it gives me (Int,Int) => Int


#2

Classes like Function2 usually do not have access to representations of their type arguments, because they are erased at runtime.

However, you could make your own function types which additionally store this info:

import scala.reflect.{ClassTag,classTag}

abstract class PrintedFunction2[A0:ClassTag,A1:ClassTag,B:ClassTag] extends ((A0,A1) => B) {
  def apply(a0: A0, a1: A1): B
  override def toString() = s"(${classTag[A0]},${classTag[A1]}) => ${classTag[B]}"
}

Note that in your example, you don’t need to explicitly instantiate Function2, you can use the lambda syntax:

val intFunction: (Int,Int) => Int = (v1, v2) => v1 + v2

In principle, that should also work with our PrintedFunction2 from Scala 2.12 on, thanks to support for SAM type lambdas. But since it requires additional implicit arguments, Scala does not quite seem to handle the lambda syntax.
I managed to make it work with an implicit conversion, though:

  implicit def toPF[A0:ClassTag,A1:ClassTag,B:ClassTag](f:(A0,A1)=>B):PrintedFunction2[A0,A1,B] = new PrintedFunction2[A0,A1,B] {
    def apply(a0: A0, a1: A1): B = f(a0,a1)
  }

Then, in the REPL:

scala> val f: PrintedFunction2[String,Int,String] = (x,y) => x * y
f: PrintedFunction2[String,Int,String] = (java.lang.String,Int) => java.lang.String

scala> println(f)
(java.lang.String,Int) => java.lang.String

scala> f("ok!",3)
res1: String = ok!ok!ok!

#3

I had implemented it with TypeTag and Implicit conversion too,


But I am keep thinking such a thing should be part of the core because <function2> nearly tells nothing, so does the lambda one ,like

  val intFunction = (a:Int,b:Int) => a + b
  println(intFunction)

gives you

Test$$$Lambda$10/905544614@7f690630


#4

And traits can’t have type parameter with context bound too :frowning:


#5

This encoding increases runtime footprint and cost of creating the lambda. A better toString is not worth that price for every single anonymous function in a Scala codebase.