HList 上的类型级映射
Type level mapping over a HList
我正在处理我的数据库 API 并且基本上想将列族建模为 HList
列,后者松散地是 Seq[_]
,所以我在某处有一个类似 Column[String]::Column[Int]::Column[Double]::HNil
的类型,所有元素共享一个公共类型构造函数。
表达行类型的最简单方法是什么,即 String::Int::Double::HNil
,从上面给出的类型,本质上展开内部类型?
我目前的推理是,由于 shapeless 可以在给定 poly
的情况下对 HList
进行映射,因此应该能够(滥用)使用 [=17= 的依赖类型 Out
] 特质。
我能想到的一件事就是在正确的情况下实现无用的 poly
,例如对所有 T
执行 Case.Aux[Column[T],T]
,然后为所有 Mapper
调用 Mapper
it et voilá,我有我的 Out
,但这感觉有点老套,我不确定它是否有效。
另一方面,我对依赖类型和类型递归还不太满意,真的想尝试并实现 shapeless 显然已经实现的东西。
感谢您的任何意见!
尝试
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
}
}
我正在处理我的数据库 API 并且基本上想将列族建模为 HList
列,后者松散地是 Seq[_]
,所以我在某处有一个类似 Column[String]::Column[Int]::Column[Double]::HNil
的类型,所有元素共享一个公共类型构造函数。
表达行类型的最简单方法是什么,即 String::Int::Double::HNil
,从上面给出的类型,本质上展开内部类型?
我目前的推理是,由于 shapeless 可以在给定 poly
的情况下对 HList
进行映射,因此应该能够(滥用)使用 [=17= 的依赖类型 Out
] 特质。
我能想到的一件事就是在正确的情况下实现无用的 poly
,例如对所有 T
执行 Case.Aux[Column[T],T]
,然后为所有 Mapper
调用 Mapper
it et voilá,我有我的 Out
,但这感觉有点老套,我不确定它是否有效。
另一方面,我对依赖类型和类型递归还不太满意,真的想尝试并实现 shapeless 显然已经实现的东西。
感谢您的任何意见!
尝试
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
}
}