In the type system, it is not possible to force use of as-is, without reflection.
The best way to do this is to have a type-type, such as NonEraseable[A] , which indicates that the type does not have type parameters that will be deleted at run time. Implicit NonEraseable[A] in scope should mean that A has no type parameters. Seeing that it will be tiring to create manually, an implicit macro can complete the task:
import scala.language.experimental.macros import scala.reflect.macros.blackbox.Context trait NonEraseable[A] object NonEraseable { implicit def ev[A]: NonEraseable[A] = macro evImpl[A] def evImpl[A](c: Context)(implicit tt: c.WeakTypeTag[A]): c.Expr[NonEraseable[A]] = { import c.universe._ val tpe = weakTypeOf[A] if(tpe.dealias.typeArgs.isEmpty) c.Expr[NonEraseable[A]](q"new NonEraseable[$tpe] {}") else c.abort(c.enclosingPosition, s"$tpe contains parameters that will be erased at runtime.") } }
Use Case:
def onlySimple[A : NonEraseable](value: A): Unit = println(value) scala> onlySimple(1) 1 scala> onlySimple(List(1, 2, 3)) <console>:13: error: List[Int] contains parameters that will be erased at runtime. onlySimple(List(1, 2, 3)) ^
Using this, you can provide, at compile time, a type A parameter with a context NonEraseable β the type of type you want. (Assuming you are not tricking or manually creating an instance of a type class)
source share