从 类 类型的列表构造一个数据类型
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
作为直接外部类型构造函数的元素类型。如果你想容纳像 Name
和 Age
这样的类型,它们通过子类型隐藏 Col
,那么可以通过考虑子类型的 Comapped
的变体来实现。
鉴于此代码:
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
作为直接外部类型构造函数的元素类型。如果你想容纳像 Name
和 Age
这样的类型,它们通过子类型隐藏 Col
,那么可以通过考虑子类型的 Comapped
的变体来实现。