Подходят ли 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

По сути, похоже, что вы хотите отобразить свой аргумент HLista, оборачивая каждый элемент в TypedHandle а затем оборачивая в результате HList в TypedLink, Во всех случаях обертки должны быть параметризованы точно по типам их содержимого.

Как видно выше, это возможно с помощью бесформенного HListmap, Здесь есть два ключевых ингредиента. Во-первых, определение полиморфного функционально-подобного значения MkTypedHandle который может быть нанесен на карту через HLista создавая HList из TypedLinkобернутые элементы. А во-вторых, неявный свидетель mapper который управляет работой карты.

Я лучше отвечу, как вы ссылаетесь на мой блог. TList - это просто HList без хранения значений, т. Е. Существует только представление типа списка, но не представление во время выполнения. Одним из преимуществ является то, что он облегчает различные, возможно, более эффективные типы хранения значений, например, массивы (HArray в Metascala). Списки TL можно также использовать для моделирования объединяемых типов (в основном, наборов типов), однако система типов Scala недостаточно мощна, чтобы делать это исключительно на уровне типов (я думаю, что система типов Haskell).

Другие вопросы по тегам