考虑这个示例,其中Listable
旨在混合到案例类的伴随对象中。因此,为了调用Writer.grid
,必须有一个A
扩展的伴生对象Listable[A]
,并在其中implicit Writer[A]
定义。(例如,将任意列表转换为Listable
CSV 格式。)
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
,而A
inw: 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
以使其工作?(或其他结构变化)