как сделать Scala canBuildFrom для построения типа коллекции от Seq до Set

Я экспериментировал с трейтом CanBuildFrom на Scala, он выглядит нормально, когда я пытаюсь автоматически преобразовать тип Array в тип Seq, я думаю, причина в том, что у нас есть CanBuildFrom[Array, T, Seq[T]] в области видимости. Однако, если я попытаюсь преобразовать массив в набор, это не сработает. Кроме того, преобразование последовательности в набор также не работает. Мне просто интересно, должен ли я определить неявный объект-компаньон CanBuildFrom того же типа для реализации преобразования? Если это так, почему scala не предоставляет его по умолчанию, причина, по которой Set - это функция?

Вот код, который для Array to Seq

def transform[U[_]](col: Array[String])(implicit cbf: CanBuildFrom[Array[String], String, U[String]]): U[String] = {
    val builder = cbf()

    for (ele <- col) builder += ele

    builder.result()
  }

CanBuildFromSpec.transform[Seq](Array("123", "3"))

Если я хочу преобразовать массив в набор или список, он не работает

CanBuildFromSpec.transform[List](Array("123", "3")) //compilation error, cannot construct
CanBuildFromSpec.transform[Set](Array("123", "3")) //compilation error, cannot construct

person Xiaohe Dong    schedule 30.05.2014    source источник
comment
Вы можете указать collection.breakOut в качестве CanBuildFrom для вашего transform, чтобы позволить вам создать любую коллекцию (любую, которая может содержать как минимум строки). Либо можно объявить неявный CanBuildFrom нужного типа.   -  person wingedsubmariner    schedule 30.05.2014


Ответы (1)


Нет необходимости изобретать велосипед — коллекции Scala имеют метод to[C[_]], который позволяет конвертировать по вашему желанию:

scala> List(1, 2, 3).to[Vector]
res0: Vector[Int] = Vector(1, 2, 3)

scala> Array(1, 2, 3).to[Seq]
res1: Seq[Int] = Vector(1, 2, 3)

scala> Seq(1, 2, 3).to[Set]
res2: Set[Int] = Set(1, 2, 3)

Кстати, CanBuildFrom был введен не для легкой конвертируемости. Это было необходимо для того, чтобы такие операции, как map() или filter(), сохраняли исходные типы коллекций.

Также Array преобразуется в Seq автоматически не из-за CanBuildFrom (это означало бы, что содержимое массива копируется в новую последовательность, что может быть довольно неэффективно), а из-за неявного преобразования массивов в их оболочки, обеспечивающие интерфейс Seq.

person Vladimir Matveev    schedule 30.05.2014
comment
Спасибо за ваш комментарий, я знаю, что могу что-то делать, но CanBuildForm очень полезен для универсального программирования в Collection. Например, если я хочу применить логику расчета для коллекции и не хочу дублировать функцию для другой коллекции, хорошим выбором будет CanBuildForm. Таким образом, в данном случае asInstanceof или to не то, что я ищу. - person Xiaohe Dong; 30.05.2014