我有这个代码将任意大小的类转换为HList
import shapeless._
import syntax.singleton._
val h = Record('a ->> 1, 'b ->> 2)
@ h.hs
res91: cmd90.<refinement>.this.type.Out = 1 :: 2 :: HNil
我想用它如下:
@ h.hs.keys //error: could not find implicit value for parameter keys: shapeless.ops.record.Keys[this.Out]
@ ('a ->> 1 :: 'b ->> 2 :: HNil).keys //works ok
但转换后不会保留密钥。与创建相同的HList相反:
&&
问题是如何在记录中保留关键信息。
答案 0 :(得分:2)
您错误地使用了记录。
'a ->> 1
,'b ->> 2
之类的内容不应单独使用,应在HList
'a ->> 1 :: 'b ->> 2 :: HNil
内使用。
当您写Record('a ->> 1, 'b ->> 2)
时,Record
的参数被视为Tuple2
。由于Tuple2
是一个案例类,LabelledGeneric
会将其隐式转换为HList
(实际上是一个无形的'记录)。看看你的h
,它的类型非常奇怪(伪代码):
Record['_1 -> 'a -> Int :: '_2 -> 'b -> Int :: HNil]
(_1
和_2
是Tuple2
)的字段名称。
所以如何修复你的代码取决于你真正想要得到的东西(我不确定)。一种可能的方法是
// class Record[H <: HList](val hs: H)
object Record {
def apply[P <: Product, L <: HList](p: P)(implicit gen: LabelledGeneric.Aux[P, L]) = /*new Record[L](*/gen.to(p)/*)*/
}
case class MyCaseClass(a: Int, b: Int)
val h = Record(MyCaseClass(1, 2))
h/*.hs*/ // 1 :: 2 :: HNil
h/*.hs*/.keys // 'a :: 'b :: HNil
('a ->> 1 :: 'b ->> 2 :: HNil).keys // 'a :: 'b :: HNil
我希望有类似
Record('a ->> 1, 'b ->> 2)
...或可能Record(('a', 1), ('b', 2))
的内容 作为输入,HList'a ->> 1 :: 'b ->> 2 :: HNil
作为输出。
然后你不需要LabelledGeneric
。您可以将Record('a ->> 1, 'b ->> 2)
转换为元组('a ->> 1, 'b ->> 2)
(如果您定义了Record.unapply(...).get
,则为case class Record(p: Product)
),然后将此tuple into HList:
import shapeless.{::, HNil}
import shapeless.syntax.std.tuple._
import shapeless.syntax.singleton._
('a ->> 1, 'b ->> 2).productElements == 'a ->> 1 :: 'b ->> 2 :: HNil // true