从 类 类型的列表构造一个数据类型

Construct a type from HList of type classes

鉴于此代码:

abstract class Col[A](val name: String)

case object Name extends Col[String]("name")
case object Age extends Col[Int]("age")

val cols = Name :: Age :: HNil

type TableDef = ??? // such that `type TableDef = String :: Int :: HNil`

如何以通用方式导出 TableDef?我怀疑它必须是一个宏,以便它可以采用 Col[_] 中的任意 HList

您可以通过 shapeless.ops.Comapped

完成大部分行程
scala> import shapeless._, ops.hlist._
import shapeless._
import ops.hlist._

scala> Comapped[Col[String] :: Col[Int] :: HNil, Col]
res0: shapeless.ops.hlist.Comapped[shapeless.::[Col[String],shapeless.::[Col[Int],shapeless.HNil]],Col]{type Out = shapeless.::[String,shapeless.::[Int,shapeless.HNil]]} = shapeless.ops.hlist$Comapped$$anon2@69bb4bc0

scala> type TableDef = res0.Out
defined type alias TableDef

scala> val foo: TableDef = "foo" :: 23 :: HNil
foo: TableDef = foo :: 23 :: HNil

scala> val foo: TableDef = "foo" :: true :: HNil
<console>:18: error: type mismatch;
 found   : shapeless.::[String,shapeless.::[Boolean,shapeless.HNil]]
 required: TableDef
    (which expands to)  shapeless.::[String,shapeless.::[Int,shapeless.HNil]]
       val foo: TableDef = "foo" :: true :: HNil
                                 ^

请注意,这依赖于具有 Col 作为直接外部类型构造函数的元素类型。如果你想容纳像 NameAge 这样的类型,它们通过子类型隐藏 Col,那么可以通过考虑子类型的 Comapped 的变体来实现。