Неявное преобразование между типами коллекций Scala - PullRequest
5 голосов
/ 13 января 2011

Я бы хотел неявно выполнить преобразование между объектом Scala XML Elem и другим представлением элемента XML, в моем случае - dom4j Element. Я написал следующие неявные преобразования:

implicit def elemToElement(e: Elem): Element = ... do conversion here ...
implicit def elementToElem(e: Element): Elem = ... do conversion here ...

Пока все хорошо, это работает.

Теперь мне также нужны коллекции указанных элементов для преобразования в обе стороны. Во-первых, мне обязательно нужно написать дополнительные методы преобразования? Вещи, похоже, не сработали, если бы я этого не сделал.

Я пытался написать следующее:

implicit def elemTToElementT(t: Traversable[Elem]) = t map (elemToElement(_))
implicit def elementTToElemT(t: Traversable[Element]) = t map (elementToElem(_))

Это не выглядит слишком идеальным, потому что если метод преобразования принимает Traversable, он также возвращает Traversable. Если я передаю Список, я также получаю Traversable. Поэтому я предполагаю, что преобразование должно быть как-то параметризовано.

Так, каков стандартный способ записи этих преобразований, чтобы они были как можно более общими?

Ответы [ 2 ]

2 голосов
/ 13 января 2011

Это нетривиально, поэтому, чтобы получить то, что вы хотите, я думаю, вам придется пойти немного глубже.Эта статья многое объясняет о том, как работают коллекции Scala (и интересно читать это тоже): http://www.artima.com/scalazine/articles/scala_collections_architecture.html

Вы в основном пытаетесь сделать то же самое, что List.map (...) (или TraversableLikeкоторый имеет реализацию) и аналогичные методы .... только с неявным преобразованием в дополнение.

Обновление:

Я начал немного экспериментировать с этим и написал преобразование на основе того, что TraversableLike.карта (...) делает.Однако я обнаружил, что это работает даже без него.Похоже, что Scala поддерживает его из коробки (по крайней мере, на моей машине :-)):

case class Element(e: Elem)
implicit def elemToElement(e: Elem): Element = Element(e)
implicit def elementToElem(e: Element): Elem = e.e

val a: List[Element] = List(<a/>, <b/>, <c/>)
val b: List[Elem] = List(Element(<a/>), Element(<b/>), Element(<c/>))
val c: Set[Element] = Set(<a/>, <b/>, <c/>)

Это было то, что вы хотели?

1 голос
/ 13 января 2011

Я думаю, что это может зайти слишком далеко.Тем более, что вы можете просто использовать метод конвертации на карте

val listOfElements = listOfElems map elemToElement(_)

Я думаю, что краткость уровня, к которой вы стремитесь, входит в запутывание.Я хотел бы создать конвертерный слой и работать только в одном из представлений, чтобы избежать путаницы.

...