TypeTag for case classes

2.2k Views Asked by At

I would like to make a case class Bla that takes a type parameter A and it knows the type of A at runtime (it stores it in its info field).

My attempt is shown in the example below. The problem is that this example does not compile.

case class Bla[A] (){
  val info=Run.paramInfo(this) // this does not compile
}
import scala.reflect.runtime.universe._

object Run extends App{
  val x=Bla[Int]
  def paramInfo[T](x:T)(implicit tag: TypeTag[T]): String = {
    val targs = tag.tpe match { case TypeRef(_, _, args) => args }
    val tinfo=s"type of $x has type arguments $targs"
    println(tinfo)
    tinfo
  }
  paramInfo(x)
}

However when I comment val info=Run.paramInfo(this) then the program runs fine and prints:

type of Bla() has type arguments List(Int)

Is there a way to make this example below compile ? (or in some other way achieve the same goal, i.e. that a case class is self aware of the type of it's type parameter?)

2

There are 2 best solutions below

0
Tzach Zohar On BEST ANSWER

You just need to pass the implicit type tag parameter to the case class constructor (otherwise the type information is lost before calling paraInfo which requires it):

case class Bla[A : TypeTag]() { ... }

Which is shorthand for:

case class Bla[A](implicit tag: TypeTag[A]) { ... }
3
flavian On

There's little point in using reflection based APIs for this, shapeless has a typeclass that exposes compile time information to runtime using an implicit macro.

import shapeless.Typeable


class Test[T : Typeable] {
  def info: String = implicitly[Typeable[T]].describe
}

It's also relatively easy to roll your own thing here, with the added inconvenience of having to compile the implicit macro in a different compilation unit than whatever is using it.