我正在寫一個通用類型類(用於DynamoDB的編解碼器)以無形式派生代碼。我有一個不使用案例類字段名稱的版本,完全基於類的字段順序與DynamoDB響應中的屬性順序相匹配的想法。它使用Generic
和通常的deriveHNil
,deriveHCons
方法,例如在此描述:https://meta.plasm.us/posts/2015/11/08/type-classes-and-generic-derivation/。如何從無形記錄中爲通用類型類派生提取標籤
現在我想要一個使用字段名稱查找相關DynamoDB屬性的版本。我目前的想法是大部分重用先前(基於訂單)版本的方法,並且另外編譯器通過LabelledGeneric
和shapeless.ops.record.Keys
提供字段名稱。但是我堅持如何正確使用Keys
功能。
的想法是這樣的:功能hconsDecoder
應做一次兩件事情:解構HList
運行在它的頭+尾decode
操作,同時還提取從上述頭的標籤。 LabelledGeneric
應提供HList
與字段上的標籤,以便H
類型參數在hconsDecoder
將是記錄中的條目,包含相關信息。但是因爲Keys
只能在HList
上工作,所以我創建了一個單例H :: HNil
來運行Keys
。
這裏是我的代碼部分:
trait FieldDecoder[A] {
def decode(a: AttributeValue): Option[A]
}
trait RecordDecoder[A] {
def decode(s: Seq[Attribute]): Option[A]
}
object RecordDecoderInstances {
implicit val hnilDecoder = new RecordDecoder[HNil] {
override def decode(s: Seq[Attribute]): Option[HNil] = {
Some(HNil)
}
}
object toName extends Poly1 {
implicit def keyToName[A] = at[Symbol with A](_.name)
}
implicit def hconsDecoder[H: FieldDecoder, T <: HList: RecordDecoder](
implicit kk: Keys[H :: HNil]#Out,
m: Mapper[toName.type, Keys[H :: HNil]#Out]) =
new RecordDecoder[H :: T] {
override def decode(s: Seq[Attribute]): Option[H :: T] = {
val attrName = (kk map toName).head.asInstanceOf[String] // compile error here
for {
h <- implicitly[FieldDecoder[H]]
.decode(s.filter(_.name == attrName).head.value)
t <- implicitly[RecordDecoder[T]]
.decode(s.filterNot(_.name == attrName))
} yield h :: t
}
}
}
鑑於此代碼,編譯器錯誤是:could not find implicit value for parameter c: shapeless.ops.hlist.IsHCons[m.Out]
。我已經嘗試了不同的版本,總是面臨着implicit not found
錯誤的一些變化。底線是,由於某種原因,Keys
不適用於H :: HNil
結構。
這是我對Shapeless的第一次認真的嘗試,我不知道我是否以正確的方式。對於這個特殊的錯誤和我的方法,我會很感激。
我不知道這種方法是否適用於嵌套案例類? – Haspemulator