第一部分
假设我有一个类型类trait Show[T] { def print(t: T): String }
,其中包含String
和Int
的实例。假设我有一个值,其特定类型仅在运行时知道:
val x: Any = ...
如何获取相应的类型类实例(在运行时,因为我们不能静态地知道类型)并使用它做一些事情。
请注意,定义一个字面上只给我们类型类实例的方法是不够的:
def instance(x: Any): Show[_]
由于Show.print
需要静态已知的参数类型T
,我们仍然无法对instance
的结果执行任何操作。实际上,我们需要能够动态调度到使用实例的已定义函数,例如:
def display[T](t: T)(implicit show: Show[T]) = "show: " + show.print(t) + "\n"
因此,假设定义了display
,我们如何调用display
,传递适当的Show
实例。即正确调用display(x)
的东西。
Miles Sabin在这里使用运行时编译(Scala eval)完成了这个,作为" staging"的一个示例,但只有备用文档来说明发生了什么:
Miles的方法可以放入图书馆吗?此外,这种方法的局限性是什么?关于像Seq[T]
这样的泛型类型?
第二部分
现在假设T
受到密封类型的限制(这样可以枚举所有子类型):
trait Show[T <: Foo]
sealed trait Foo
case class Alpha(..) extends Foo
case class Beta(..) extends Foo
在这种情况下,我们可以使用宏而不是运行时编译吗?并且可以在某些库中提供此功能吗?
我最关心的是Scala 2.12,但如果解决方案在2.11或2.10中有效,那么值得一提。