Отображение уровня типа по HList - PullRequest
0 голосов
/ 09 февраля 2019

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

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

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

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

1 Ответ

0 голосов
/ 09 февраля 2019

Попробуйте

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
  }
}

или

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
  }
}
...