Универсальный (кортежный) тип Scala с несколькими подтипами

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

type T <: Tuple1[_] with Tuple2[_,_] with Tuple3[_,_,_] with Tuple4[_,_,_,_] with Tuple5[_,_,_,_,_]

а затем структура данных

val map = new HashMap[Int, T]

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

Спасибо, Ю.К.


person Y.K.    schedule 09.12.2012    source источник
comment
Может тебе понравится Product? Да, он позволяет передавать не только кортежи, но и довольно общий   -  person om-nom-nom    schedule 09.12.2012
comment
Почему вы ограничиваете тип значения своей структуры данных только кортежами? Планируете ли вы использовать какое-либо свойство, общее для всех типов кортежей?   -  person n. 1.8e9-where's-my-share m.    schedule 09.12.2012
comment
Спасибо за ваши ответы. Я ограничиваю ds кортежами, так как это то, что пользователь в конечном итоге вводит (например, (3, 4.5, foo)), и я хочу избежать преобразования типов. Я мог бы использовать продукт, да, но тогда мне нужно было бы сопоставить регулярное выражение для разных типов, когда я верну каждый T? Что-то вроде varT match {case (,) = ›... case (,, _) =› ...} и так далее ... верно?   -  person Y.K.    schedule 09.12.2012
comment
Я не уверен, что точно понимаю, что вы пытаетесь сделать, но обобщение арности кортежа (без отказа от безопасности типов) в Scala болезненно без помощи чего-то вроде реализации гетерогенного списка (я бы рекомендовал Shapeless).   -  person Travis Brown    schedule 09.12.2012
comment
Я не вижу, какие преобразования типов следует исключить. Вы можете указать на некоторые из них? Если пользователь в конечном итоге войдет в (подтипы) Any, не устранит ли ограничение T до Any преобразование типов?   -  person n. 1.8e9-where's-my-share m.    schedule 09.12.2012
comment
@ Y.K. что вы имеете в виду, говоря мне нужно было бы иметь соответствие регулярного выражения для разных типов, когда я верну каждый T обратно? Вам нужно знать точный класс и параметризовать с его помощью функцию что ли?   -  person om-nom-nom    schedule 09.12.2012


Ответы (1)


Первое решение - использовать Product, как сказано в @ om-nom-nom. Действительно, это единственный общий супертип всех кортежей.

val map = Map.empty[Int, Product]
map + (2 -> ("a", "b"))

А затем использовать методы productArity, productElement и productIterator для обработки возвращаемого значения.

Вы также можете использовать карту списка (или любую проиндексированную коллекцию).

val map = Map.empty[Int, List[_]]
map + (3 -> ("a" :: "b" :: "c" :: Nil))
map + (2 -> List("a", "b"))

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

person Lomig Mégard    schedule 09.12.2012