Let's say I have a type called LongArrayWritable, that is a boxed representation of an Array of Longs. I have implicit definitions that convert between these types:
implicit def boxLongArray(array: Array[Long]) : LongArrayWritable { /*elided*/}
implicit def unboxLongArray(array: LongArrayWritable) : Array[Long] { /*elided*/}
Now, I also have implicits that convert between java.lang.Iterable and scala.collection.List[X] in their generic form:
implicit def iterator2list[X](it : java.lang.Iterable[X]) : List[X] { /* elided */ }
implicit def list2iterator[X](list : List[X]) : java.lang.Iterable[X] { /* elided */ }
With these definitions, can the scala compiler infer an implicit conversion between java.lang.Iterable[LongArrayWritable] and List[Array[Long]] (the equivalent of iterator2list(iterator).map(unboxLongArray(_))
), or is this beyond the capabilities of implicits, and therefore requires it's own (explicit?) implicit definition?
Thanks,
Tim
There is a post that covers this question: How can I chain implicits in Scala? . Essentially, you need to have a view bound for the conversion to LongArrayWritable
. That means, the implicit def
that converts to LongArrayWritable
receives an implicit argument (called view bound) so that the argument to this def
is not directly an Array
but some type that can be converted to an Array
:
object LongArrayWritable {
implicit def fromArraySource[A <% Array[Long]](a: A): LongArrayWritable = apply(a)
}
case class LongArrayWritable(a: Array[Long])
def test(a: LongArrayWritable): Unit = println("OK")
now this works for Arrays:
test(Array( 1L, 2L, 3L))
however, since Array
is not an Iterable
and there are no default conversions from Iterable
to Array
in scope, you need to add one:
implicit def iterable2Array[A: ClassManifest](i: Iterable[A]): Array[A] = i.toArray
then it works:
test(List(1L, 2L, 3L))
the view bound A <% Array[Long]
is a shortcut for an implicit argument of type A => Array[Long]
, so you could have also written
implicit def fromArraySource[A](a: A)(implicit view: A => Array[Long]) ...