Consider this example, where Listable
is intended to mixed into the companion object of a case class. Therefore, in order to call Writer.grid
, one must have a companion object A
that extends Listable[A]
, with an implicit Writer[A]
defined within. (Say for example, to convert a list of an arbitrary Listable
to a CSV format.)
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]
}
And here's a naive implementation:
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)
}
}
This compiles, but cannot work because listable: A
really refers to the object Test
, and A
in w: Writer[A]
refers to the case class Test
, so calling Writer.grid(Test)
fails to conform to the type bounds.
I can work around this problem somewhat by ditching Listable
and requiring an implicit List[A]
in the signature of grid
:
def grid[A](implicit w: Writer[A], list: List[A]): String = ...
But I'd prefer to:
- Not require such an implicit function that could produce unexpected results.
- Not use a special type to wrap
list
, as it will also be used elsewhere. - Keep the definition of the
grid
method outside ofListable
.
Is it possible to re-work the signature of Writer.grid
to make this work? (or other structural changes)