Подходят ли HList/KList в качестве параметра метода? Как сослаться на? Тип списка?
Я обнаружил HList / KList, они довольно крутые. У меня есть фактический вариант использования, в котором очень полезными были бы контейнеры разнородной типизации и переменной длины с сохраненной информацией о типах (для получения дополнительной информации см. Фон ниже). Однако я не понял использование H/KList в качестве параметра метода, где я вынужден полностью аннотировать тип или потерять информацию о типе. Можно ли даже использовать H/KLists в качестве параметра, если полный тип, конечно, неизвестен? Как обратиться к H/KList без потери информации о типе?
Можно ли использовать "списки типов" для обозначения набора разнородных параметров и параметров типа переменной длины? Здесь говорится: ... the types of the elements can be tracked separate from the actual element values. To do this we create an purely abstract type (it has no instances) which models a list of types, let's call it TList.
Я поиграл с этим, но еще не понял, как использовать его для аннотации типа HList в качестве параметра.
В принципе, я хочу что-то вроде этого:
implicit def hlistToTypedLink[TL](a: HList[TL]):TypedLink[TL] = new TypedLink[TL](a.map(a:X => new TypedHandle[X]))
где TL относится к списку типов, а X к типу текущего элемента. Таким образом, здесь HList должен отображаться в другой контейнер типа Tuple, TypedLink, параметризованный списком типов TL. Элементы должны быть обернуты каждый в еще один параметризованный контейнер TypedHandle, типизированный с текущим типом X.
Это возможно?
Я видел Shapeless' HList и его метод "унификации", но проблема остается той же: я не знаю, как ссылаться на него в списке параметров, кроме переменной длины.
Моя вторая надежда заключалась в использовании KList. Это применимо в моем случае, потому что TypedHandle является общим контейнером с тем же конструктором. С KList, кажется, легче набирать аннотации, в соответствии с apocalisp:
val m = List(1, 2, 3, 4) :^: List("str1", "str2") :^: KNil
будет иметь тип:
KCons[Int,java.lang.String :: HNil,List]
Однако проблема остается той же: в определении метода я не могу знать, будет ли это
KCons[String, Int :: HNil, TH]
или
KCons[Foo, Bar, Baz :: HNil, TH]
поэтому я не знаю, как ввести аннотировать KList в качестве параметра метода либо.
Спасибо за любые подсказки!
Справочная информация: я пишу удобные расширения Scala для превосходной базы данных OO- & Graph HypergraphDB. Гиперграницы Hypergraphdb, HGLink, в основном являются кортежами HGHandle. HGHandle относится к атомам, которые сами по себе являются типизированными. Следовательно, HGLink сам по себе будет гетерогенным типом и переменной длины. Тем не менее, реализации HGLink до сих пор нетипизированы и построены с помощью нетипизированных реализаций HGHandle. Я полагаю, что система типов java не достаточно выразительна, чтобы отразить (намного превосходящую) систему типов hypergraphdb (которая, например, также имеет типы с более высоким родом).
По сути, я пытаюсь связать scala с системами типов hypergraphdb, я многому учусь, и до сих пор это было очень весело. TypedHandle уже отлично работает, помимо множества других хаков.
спасибо за любой совет.
2 ответа
Мне не совсем понятно, о чем ты просишь, но твоя hlistToTypedLink
похоже, что это может быть обработано с помощью бесформенного HList
и значения полиморфной функции,
scala> import shapeless._ ; import TypeOperators._
import shapeless._
import TypeOperators._
scala> class TypedHandle[T]
defined class TypedHandle
scala> class TypedLink[L <: HList](l : L)
defined class TypedLink
scala> object MkTypedHandle extends (Id ~> TypedHandle) {
| def apply[T](t : T) = new TypedHandle[T]
| }
defined module MkTypedHandle
scala> def hlistToTypedLink[L <: HList, M <: HList](a: L)
| (implicit mapper: MapperAux[MkTypedHandle.type, L, M]) =
| new TypedLink[M](a map MkTypedHandle)
hlistToTypedLink: [L <: HList, M <: HList](a: L)
(implicit mapper: MapperAux[MkTypedHandle.type,L,M])TypedLink[M]
scala> hlistToTypedLink(23 :: "foo" :: true :: HNil)
res0: TypedLink[TypedHandle[Int] :: TypedHandle[String] ::
TypedHandle[Boolean] :: HNil] = TypedLink@51fb5716
По сути, похоже, что вы хотите отобразить свой аргумент HList
a
, оборачивая каждый элемент в TypedHandle
а затем оборачивая в результате HList
в TypedLink
, Во всех случаях обертки должны быть параметризованы точно по типам их содержимого.
Как видно выше, это возможно с помощью бесформенного HList
map
, Здесь есть два ключевых ингредиента. Во-первых, определение полиморфного функционально-подобного значения MkTypedHandle
который может быть нанесен на карту через HList
a
создавая HList
из TypedLink
обернутые элементы. А во-вторых, неявный свидетель mapper
который управляет работой карты.
Я лучше отвечу, как вы ссылаетесь на мой блог. TList - это просто HList без хранения значений, т. Е. Существует только представление типа списка, но не представление во время выполнения. Одним из преимуществ является то, что он облегчает различные, возможно, более эффективные типы хранения значений, например, массивы (HArray в Metascala). Списки TL можно также использовать для моделирования объединяемых типов (в основном, наборов типов), однако система типов Scala недостаточно мощна, чтобы делать это исключительно на уровне типов (я думаю, что система типов Haskell).