【发布时间】:2017-04-07 07:37:59
【问题描述】:
我正在尝试在 Scala 中实现一个有点复杂的类型类示例:将类型 T 的值转换为作为库实现的字符串,用户可以为任何类型 T 扩展。所以这是所有类型类都应该实现的特征:
trait Printable[T] {
def asString(value: T): String
}
我们要调用的函数来完成这项工作:
object Printer {
def print[T](value: T)(implicit p:Printable[T]): String = p.asString(value)
}
具有一些默认类型的一系列类型类的对象(例如这里只有 int&long):
object SimpleFormats extends Formats
trait Formats {
implicit val intFormat = new Printable[Int] {
override def asString(value: Int) = value.toString
}
implicit val longFormat = new Printable[Long] {
override def asString(value: Long) = value.toString
}
}
想象一下,用户想要为其他类型扩展我们的库,例如 Float 和 Double。所以他创建了另一个对象,继承了第一个对象。这里的想法是向基对象添加新的隐式成员,以便可以为任意数量的用户提供的类型扩展类型类的默认集合:
object ExtendedFormats extends Formats {
implicit val floatFormat = new Printable[Float] {
override def asString(value: Float) = value.toString
}
implicit val doubleFormat = new Printable[Double] {
override def asString(value: Double) = value.toString
}
}
最后,使用我们库的主应用程序。有两个示例函数对不同类型进行操作,因此无法提供单个特定的隐式 Printer[T] 为:
- 对多种类型有多种操作
-
Printer事先不知道用户可以提供哪些类型。
所以主应用看起来像这样:
object Example {
// compiles OK, uses only default typeclasses
def simpleExample(implicit formats: Formats) = {
import formats._
Printer.print(42) + Printer.print(24L)
}
// compilation failed, cannot find Printable[Float]
// uses user-supplied formats
def extendedExample(implicit formats: Formats) = {
import formats._
Printer.print(42f) + Printer.print(31337.0)
}
def main(args: Array[String]): Unit = {
implicit val formats = ExtendedFormats
println(simpleExample)
println(extendedExample)
}
}
我看到 scala 编译器试图从 Formats 导入隐式,而忽略了它实际上是 ExtendedFormats 的事实。
问题:
- 有没有办法从示例中描述的子类中导入隐式?
- 对于一批用户提供的类型类是否有更好的解决方案?
【问题讨论】:
-
您可以查看simulacrum 的类型类。