我需要HList根据键和值映射生成可扩展记录,这里是我想要实现的MWE(你可以在任何REPL中复制/粘贴这个可用的无形2.0,以便重现问题)
import shapeless._; import syntax.singleton._; import record._
case class Foo[T](column: Symbol)
val cols = Foo[String]('column1) :: HNil
val values = Map("column1" -> "value1")
object toRecord extends Poly1 {
implicit def Foo[T] = at[Foo[T]] { foo =>
val k = foo.column.name
val v = values.get(k)
(k ->> v)
}
}
val r = cols.map(toRecord)
// r: shapeless.::[Option[String] with shapeless.record.KeyTag[k.type,Option[String]] forSome { val k: String },shapeless.HNil] = Some(value1) :: HNil
val value = r("column1")
// error: No field String("column1") in record shapeless.::[Option[String] with shapeless.record.KeyTag[k.type,Option[String]] forSome { val k: String },shapeless.HNil]
val value = r("column1")
Run Code Online (Sandbox Code Playgroud)
如果我尝试手动定义记录,一切都按预期工作
val q = ("column1" ->> Some("value1")) :: HNil
// q: shapeless.::[Some[String] with shapeless.record.KeyTag[String("column1"),Some[String]],shapeless.HNil] = Some(value1) :: HNil
q("column1")
// Some[String] = Some(value1)
Run Code Online (Sandbox Code Playgroud)
显然,区别在于在一种情况下KeyTag具有类型
KeyTag[String("column1"), Some[String]]
Run Code Online (Sandbox Code Playgroud)
在(非工作)其他
KeyTag[k.type,Option[String]] forSome { val k: String }
Run Code Online (Sandbox Code Playgroud)
我觉得问题是字符串k不是静态知道,但我不知道如何解决这个问题.一般来说,有没有一种方法可以从密钥列表中动态生成可扩展记录?
我担心答案是使用宏,但如果存在另一种解决方案,我会很高兴.
如果您可以Foo稍微更改定义以允许它跟踪列键的单例类型(请注意我已删除未使用的T类型参数),这不是太糟糕:
import shapeless._; import syntax.singleton._; import record._
case class Foo[K <: Symbol](column: Witness.Aux[K])
val cols = Foo('column1) :: HNil
val values = Map("column1" -> "value1")
object toRecord extends Poly1 {
implicit def atFoo[K <: Symbol] = at[Foo[K]] { foo =>
field[K](values.get(foo.column.value.name))
}
}
val r = cols.map(toRecord)
Run Code Online (Sandbox Code Playgroud)
然后:
scala> val value = r('column1)
value: Option[String] = Some(value1)
Run Code Online (Sandbox Code Playgroud)
请注意,我已将您的字符串键("column1")更改为符号,因为这是我们放入记录的内容.
| 归档时间: |
|
| 查看次数: |
920 次 |
| 最近记录: |