在隐含的 LabelledGeneric 中保留关键信息
retain key information in implicit LabelledGeneric
我有这段代码可以将 class 的任意大小转换为 HList
class Record[H <: HList](val hs: H)
object Record {
import shapeless.LabelledGeneric
def apply[P <: Product, L <: HList](p: P)(implicit gen: LabelledGeneric.Aux[P, L]) = new Record[L](gen.to(p))
}
我想按如下方式使用:
import shapeless._
import syntax.singleton._
val h = Record('a ->> 1, 'b ->> 2)
@ h.hs
res91: cmd90.<refinement>.this.type.Out = 1 :: 2 :: HNil
但是,转换后密钥不会保留。与创建相同的 HList 相反:
@ 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
问题是如何保留记录中的关键信息。
您使用的记录不正确。
像'a ->> 1
、'b ->> 2
这样的东西不应该单独使用,它们应该在HList
里面使用,比如'a ->> 1 :: 'b ->> 2 :: HNil
。
当你写 Record('a ->> 1, 'b ->> 2)
时,Record
的参数被认为是 Tuple2
。由于 Tuple2
是一个案例 class,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
I would like to have something like Record('a ->> 1, 'b ->> 2)
... or potentially Record(('a', 1), ('b', 2))
as an input, and an HList 'a ->> 1 :: 'b ->> 2 :: HNil
as an output.
那你就不需要LabelledGeneric
了。您可以将 Record('a ->> 1, 'b ->> 2)
转换为一个元组 ('a ->> 1, 'b ->> 2)
(如果您定义了 case class Record(p: Product)
,则为 Record.unapply(...).get
),然后 :
import shapeless.{::, HNil}
import shapeless.syntax.std.tuple._
import shapeless.syntax.singleton._
('a ->> 1, 'b ->> 2).productElements == 'a ->> 1 :: 'b ->> 2 :: HNil // true
我有这段代码可以将 class 的任意大小转换为 HList
class Record[H <: HList](val hs: H)
object Record {
import shapeless.LabelledGeneric
def apply[P <: Product, L <: HList](p: P)(implicit gen: LabelledGeneric.Aux[P, L]) = new Record[L](gen.to(p))
}
我想按如下方式使用:
import shapeless._
import syntax.singleton._
val h = Record('a ->> 1, 'b ->> 2)
@ h.hs
res91: cmd90.<refinement>.this.type.Out = 1 :: 2 :: HNil
但是,转换后密钥不会保留。与创建相同的 HList 相反:
@ 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
问题是如何保留记录中的关键信息。
您使用的记录不正确。
像'a ->> 1
、'b ->> 2
这样的东西不应该单独使用,它们应该在HList
里面使用,比如'a ->> 1 :: 'b ->> 2 :: HNil
。
当你写 Record('a ->> 1, 'b ->> 2)
时,Record
的参数被认为是 Tuple2
。由于 Tuple2
是一个案例 class,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
I would like to have something like
Record('a ->> 1, 'b ->> 2)
... or potentiallyRecord(('a', 1), ('b', 2))
as an input, and an HList'a ->> 1 :: 'b ->> 2 :: HNil
as an output.
那你就不需要LabelledGeneric
了。您可以将 Record('a ->> 1, 'b ->> 2)
转换为一个元组 ('a ->> 1, 'b ->> 2)
(如果您定义了 case class Record(p: Product)
,则为 Record.unapply(...).get
),然后
import shapeless.{::, HNil}
import shapeless.syntax.std.tuple._
import shapeless.syntax.singleton._
('a ->> 1, 'b ->> 2).productElements == 'a ->> 1 :: 'b ->> 2 :: HNil // true