Как обогатить коллекции Scala моей собственной «картой» (правильный путь)? - PullRequest
3 голосов
/ 12 декабря 2011

Я пытаюсь обогатить коллекции Scala собственным методом map, и я близок, но неявное преобразование не работает.Кроме того, есть ли что-то еще, что я здесь скучаю?Я просматриваю различные другие ресурсы в Интернете, , включая ответы SO, что этот вопрос помечен как дублирующий , и многие упускают кое-что здесь (например, C[A] <: GenTraversable[A], вместо него b()).b(xs), забыв о Array, забыв о BitSet и т. д.).

implicit def conv[A,C](xs: C)(implicit ev: C <:< GenTraversableLike[A,C]) = new {
  def mymap[B,D](f: A => B)(implicit b: CanBuildFrom[C,B,D]): D = b(xs).result // placeholder
}

scala> conv(List(1,2,3))
res39: java.lang.Object{def mymap[B,D](f: Int => B)(implicit b: scala.collection.generic.CanBuildFrom[List[Int],B,D]): D} = $$$$2c9d7a9074166de3bf8b66cf7c45a3ed$$$$anon$1@3ed0eea6

scala> conv(List(1,2,3))mymap(_+1)
res40: List[Int] = List()

scala> conv(BitSet(1,2,3))mymap(_+1)
res41: scala.collection.immutable.BitSet = BitSet()

scala> conv(BitSet(1,2,3))mymap(_.toFloat)
res42: scala.collection.immutable.Set[Float] = Set()

scala> List(1,2,3)mymap(_+1)
<console>:168: error: Cannot prove that List[Int] <:< scala.collection.IterableLike[A,List[Int]].
              List(1,2,3)mymap(_+1)
                  ^

scala> implicit def conv[A, C](xs: C)(implicit ev: C => GenTraversable[A]) = new {
     | def mymap[B,D](f: A => B)(implicit b: CanBuildFrom[GenTraversable[A],B,D]): D =
     | xs map f
     | }
conv: [A, C](xs: C)(implicit ev: C => scala.collection.GenTraversable[A])java.lang.Object{def mymap[B,D](f: A => B)(implicit b: scala.collection.generic.CanBuildFrom[scala.collection.GenTraversable[A],B,D]): D}

scala> conv(Array(1)) mymap (_+1)
res6: scala.collection.GenTraversable[Int] = ArrayBuffer(2)

scala> Array(1) mymap (_+1)
<console>:68: error: No implicit view available from Array[Int] => scala.collection.GenTraversable[A].
              Array(1) mymap (_+1)
                   ^

Ответы [ 2 ]

4 голосов
/ 12 декабря 2011

Я ответил на этот самый вопрос о выводе типа только на прошлой неделе.Вот код:

implicit def conv[A,C <: GenTraversable[A]](xs: C with GenTraversableLike[A,C]) = new {
  def mymap[B,D](f: A => B)(implicit b: CanBuildFrom[C,B,D]): D = {
    val builder = b(xs)
    xs foreach { x => builder += f(x) }
    builder.result
  }
}

Я мог бы использовать GenTraversable вместо GenTraversableLike в данном конкретном случае.Я предпочитаю последнее, потому что оно предлагает больше.

Проблема в том, что объявление [A, C <: GenTraversable[A]] не не инструктирует Scala выводить тип A из типа C.Типы выводятся на основании того, как они используются в параметрах, а затем проверяются по границам, указанным параметрами типа.

Поэтому, когда я пишу xs: C with GenTraversable[A], я сообщаю Scala, что он должен выводить A изxs.И написание GenTraversableLike[A, C] говорит Scala, что он должен выбрать коллекцию, которую возвращает C для методов, которые возвращают ту же коллекцию.Это означает, что вы можете позвонить filter и получить C назад, вместо того, чтобы вернуть GenTraversable.

Что касается желания включать представления, то я не знаю, как вы могли бы выполнить.

1 голос
/ 12 декабря 2011

Я ответил на аналогичный вопрос здесь . Вы также можете обратиться к этой теме , где Рекс Керр объясняет, как вообще выполнять такое сутенерство.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...