Преобразование из List [Vector [T]] в Vector [List [T]] в общем виде - PullRequest
4 голосов
/ 07 марта 2011

Я пытаюсь выяснить, могу ли я преобразовать List(Vector(1), Vector(2,3)) в Vector(List(1), List(2,3)) или любые два класса с возможностью прохождения универсальным образом.

Это то, что я до сих пор:

import collection.generic.CanBuildFrom
import collection.breakOut
import collection.mutable.ListBuffer

def f[A, CC[X] <: Traversable[X], DD[Y] <: Traversable[Y]](outer: DD[CC[A]])
  (implicit cbf1: CanBuildFrom[Traversable[_], A, DD[A]],
  cbf2: CanBuildFrom[Traversable[_], DD[A], CC[DD[A]]])
  : CC[DD[A]] = {
  val builder2 = cbf2()
  outer.foreach { inner =>
    val builder1 = cbf1()
    builder1 ++= inner
    builder2 += builder1.result
  }
  builder2.result
}

f(Vector(List(1), List(2,3)))(breakOut, breakOut) 
f(ListBuffer(Vector(1), Vector(2,3)))(breakOut, breakOut) 

Если я удалю breakOuts, он не скомпилируется:

f(Vector(List(1), List(2,3))) // won't work

не может найти неявное значение для параметра cbf1: scala.collection.generic.CanBuildFrom [Traversable [_], Int, scala.collection.immutable.Vector [Int]]

Есть ли какие-либо последствия, которые я могу импортировать?Любой другой способ решения этой проблемы, который не требует перерывов?


редактировать на основе ответа ретронима:

import scalaz.CanBuildAnySelf
def f[A, CC[X] <: Traversable[X] : CanBuildAnySelf, 
         DD[Y] <: Traversable[Y] : CanBuildAnySelf](outer: DD[CC[A]])
           : CC[DD[A]] = {
  val builder2 = implicitly[CanBuildAnySelf[CC]].builder[DD[A], DD[A]].apply()
  outer.foreach { inner =>
    val builder1 = implicitly[CanBuildAnySelf[DD]].builder[A, A].apply()
    builder1 ++= inner
    builder2 += builder1.result
  }
  builder2.result
}

Приятно и впечатляюще видетьчто привязка контекста CanBuildAnySelf может использоваться полностью отдельно.

Ответы [ 2 ]

5 голосов
/ 07 марта 2011

Мы делаем это в Скалазе, так что это, безусловно, возможно.

scala> import scalaz._
import scalaz._

scala> import Scalaz._
import Scalaz._

scala> List(Vector(1, 2, 3)).sequence
res1: scala.collection.immutable.Vector[List[Int]] = Vector(List(1, 2, 3), List(1, 2, 3), List(1, 2, 3))

scala> Seq(List(1), List(3)).sequence
res2: List[Seq[Int]] = List(List(1, 3))

scala> Vector(ArraySeq(1, 2, 3)).sequence
res3: scala.collection.mutable.ArraySeq[scala.collection.immutable.Vector[Int]] = ArraySeq(Vector(1, 2, 3), Vector(1, 2, 3), Vector(1, 2, 3))

Мы рассматриваем только коллекции с "хорошим поведением", то есть коллекции, которые могут содержать произвольные типы элементов, в отличие от BitSet. Это засвидетельствовано с https://github.com/scalaz/scalaz/blob/master/core/src/main/scala/scalaz/CanBuildAnySelf.scala

0 голосов
/ 07 марта 2011

Это работает:

val l = List(Vector(1), Vector(2, 3))
val v = Vector((for (v <- l) yield v.toList): _*)
...