Question

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

Was it helpful?

Solution

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]) ...
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top