从类型类的HList构造一个类型

时间:2017-02-05 14:57:55

标签: scala shapeless

鉴于此代码:

path-to-your-file

如何以通用方式派生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 HList

1 个答案:

答案 0 :(得分:1)

您可以使用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$$anon$162@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变体来实现。