考虑这个示例,其中Listable旨在混合到案例类的伴随对象中。因此,为了调用Writer.grid,必须有一个A扩展的伴生对象Listable[A],并在其中implicit Writer[A]定义。(例如,将任意列表转换为ListableCSV 格式。)
trait Listable[A] {
def list: List[A]
}
object Writer {
def grid[A <: Listable[A]](listable: A)(implicit w: Writer[A]): String = {
listable.list.map(w.write(_).mkString(",")).mkString("\n")
}
}
trait Writer[A] {
def write(a: A): List[String]
}
这是一个天真的实现:
case class Test(id: Int, text: String)
object Test extends Listable[Test] {
def list = List(Test(1, "test"))
implicit val wrt = new Writer[Test] {
def write(t: Test) = List(t.id.toString, t.text)
}
}
这可以编译,但不能工作,因为listable: A真正指的是 object Test,而Ainw: Writer[A]指的是 case class Test,所以调用Writer.grid(Test)不符合类型边界。
Listable我可以通过放弃并要求implicit List[A]签名来解决这个问题grid:
def grid[A](implicit w: Writer[A], list: List[A]): String = ...
但我更愿意:
- 不需要这样一个可能产生意外结果的隐式函数。
- 不要使用特殊类型来 wrap
list,因为它也会在其他地方使用。 grid将方法的定义保留在Listable.
是否可以重新签名Writer.grid以使其工作?(或其他结构变化)