保留隐式LabelledGeneric中的关键信息

时间:2017-09-14 10:55:09

标签: scala shapeless

我有这个代码将任意大小的类转换为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相反:

&&

问题是如何在记录中保留关键信息。

1 个答案:

答案 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_2Tuple2)的字段名称。

所以如何修复你的代码取决于你真正想要得到的东西(我不确定)。一种可能的方法是

//  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