Отображение уровня типа по HList

Я обрабатываю свой API базы данных и, по сути, хотел бы моделировать семейства столбцов как HList столбцов, причем последний может быть Seq[_], поэтому где-то у меня есть тип, подобный Column[String]::Column[Int]::Column[Double]::HNil, со всеми элементами, использующими общий конструктор типа.

Каким будет самый простой способ выразить тип строк, т. Е. String::Int::Double::HNil, из указанного выше типа, по существу разворачивая внутренние типы? Мое текущее рассуждение состоит в том, что, поскольку shapeless может создать карту над этим HList при правильном poly, следует иметь возможность (ab) использовать зависимый тип Out признака Mapper.

Одна вещь, о которой я могу думать, - это просто реализовать бесполезный poly с правильными случаями, например Case.Aux[Column[T],T] для всех Ts, затем вызвать Mapper для него и вуаля, вот и мой Out, но это кажется немного взломанным, и я не уверен это даже сработает. С другой стороны, я еще не чувствую себя настолько комфортно в связи с зависимыми типами и рекурсией типов, чтобы действительно попытаться реализовать что-то, что, очевидно, уже делает бесформенный.

Спасибо за любой вклад!


person rau    schedule 09.02.2019    source источник


Ответы (1)


Пытаться

import shapeless.PolyDefns.~>
import shapeless.ops.hlist.{Comapped, NatTRel}
import shapeless.{HList, HNil, Id}

object App {
  case class Column[A](a: A)

  def extract[L <: HList, L1 <: HList](l: L)(implicit
    comapped: Comapped.Aux[L, Column, L1],
    natTRel: NatTRel[L, Column, L1, Id],
  ): L1 = natTRel.map(new (Column ~> Id) { def apply[T](col: Column[T]) = col.a }, l)

  val result = extract(Column(1) :: Column("a") :: HNil)

  def main(args: Array[String]): Unit = {
    println(result) // 1 :: a :: HNil
  }
}

or

import shapeless.PolyDefns.~>
import shapeless.ops.hlist.NatTRel
import shapeless.{HList, HNil}

object App {
  case class Column[A](a: Seq[A])

  def extract[L <: HList, L1 <: HList](l: L)(implicit
    natTRel: NatTRel[L, Column, L1, Seq],
  ): L1 = natTRel.map(new (Column ~> Seq) { def apply[T](col: Column[T]): Seq[T] = col.a }, l)

  val result = extract(Column(Seq("a", "b")) :: Column(Seq(1, 2)) :: Column(Seq(10.0, 20.0)) :: HNil)

  def main(args: Array[String]): Unit = {
    println(result) // List(a, b) :: List(1, 2) :: List(10.0, 20.0) :: HNil
  }
}
person Dmytro Mitin    schedule 09.02.2019
comment
Большое спасибо! Просто чтобы я понял, что здесь происходит: я использую естественное преобразование и преобразовываю (отображаю?) Любой конструктор типа (столбец? Эффект? Функтор?) В тип идентичности (монада? Функтор? Эффект?) С помощью из нескольких загадочных подтекстов, которые нужно уметь расшифровать из документации и результатов вычислений в правильном типе? Угадай, сегодня так же хорошо, чтобы начать изучать какую-то глубокую бесформенную магию, как и в любой другой день. - person rau; 09.02.2019