Могут ли Scala влиять на преобразование типов с более высоким родом? - PullRequest
3 голосов
/ 30 марта 2011

Допустим, у меня есть тип с именем LongArrayWritable, который является коробочным представлением массива длинных.У меня есть неявные определения, которые конвертируются между этими типами:

implicit def boxLongArray(array: Array[Long]) : LongArrayWritable { /*elided*/}
implicit def unboxLongArray(array: LongArrayWritable) : Array[Long] { /*elided*/}

Теперь у меня также есть импликации, которые конвертируют между java.lang.Iterable и scala.collection.List [X] в их общую форму:

implicit def iterator2list[X](it : java.lang.Iterable[X]) : List[X] { /* elided */ }
implicit def list2iterator[X](list : List[X]) : java.lang.Iterable[X] { /* elided */ }

С этими определениями может ли компилятор scala выводить неявное преобразование между java.lang.Iterable [LongArrayWritable] и List [Array [Long]] (эквивалент iterator2list(iterator).map(unboxLongArray(_))), или это за пределами возможностейпоследствий, и, следовательно, требует своего (явного?) неявного определения?

Спасибо,

Тим

1 Ответ

7 голосов
/ 30 марта 2011

Есть сообщение, которое освещает этот вопрос: Как я могу связать импликации в Scala? . По сути, вам необходимо иметь привязку вида для преобразования в LongArrayWritable. Это означает, что неявный def, который преобразуется в LongArrayWritable, получает неявный аргумент (называемый ограниченным представлением), так что аргумент этого def не является непосредственно Array, а некоторым типом, который может быть преобразован в 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")

теперь это работает для массивов:

test(Array( 1L, 2L, 3L))

однако, поскольку Array не является Iterable и нет конверсий по умолчанию от Iterable до Array в области видимости, вам необходимо добавить одно:

implicit def iterable2Array[A: ClassManifest](i: Iterable[A]): Array[A] = i.toArray

тогда это работает:

test(List(1L, 2L, 3L))

Граница представления A <% Array[Long] является ярлыком для неявного аргумента типа A => Array[Long], поэтому вы могли бы также написать

implicit def fromArraySource[A](a: A)(implicit view: A => Array[Long]) ...
...