我正在尝试使用无形生成一个类型类,用于在编译时返回具有特定注释的案例类字段的值。
给定了一个 Scala 注释案例类和一个通用案例类,该类型类Identity[T]
应返回使用此类注释注释的“单一”属性的值。
trait Identity[T] {
def apply(t: T): Long
}
final case class Id() extends scala.annotation.StaticAnnotation
case class User(@Id id: Long, account_id: Int, name: String, updated_at: java.time.Instant)
并给出案例类和类型类的实例
val identity = Identity[User] // implicit summoner
val user = User(1009, 101, "Alessandro", Instant.now())
val value = identity(user)
我想value回来1009
我试图玩弄下面的代码片段,但我确实得到了计算Symbol带注释字段的名称。
object WithShapeless {
import MyAnnotations.Id
import shapeless._
import shapeless.ops.hlist
import shapeless.ops.record.Keys
import shapeless.record._
// select the field symbol with the desired annotation, if exists
object Mapper extends Poly1 {
implicit def some[K <: Symbol]: Case.Aux[(K, Some[Id]), Option[K]] = at[(K, Some[Id])] {
case (k, _) => Some(k)
}
implicit def none[K <: Symbol]: Case.Aux[(K, None.type), Option[K]] = at[(K, None.type)] {
case (k, _) => Option.empty[K]
}
}
implicit def gen[A, HL <: HList, AL <: HList, KL <: HList, ZL <: HList, ML <: HList](
implicit
generic: LabelledGeneric.Aux[A, HL],
annots: Annotations.Aux[Id, A, AL],
keys: Keys.Aux[HL, KL],
zip: hlist.Zip.Aux[KL :: AL :: HNil, ZL],
mapper: hlist.Mapper.Aux[Mapper.type, ZL, ML],
ev0: hlist.ToList[ML, Option[Symbol]]
): Identity[A] = new Identity[A] {
val zipped: ZL = zip(keys() :: annots() :: HNil)
val annotatedFields: ML = mapper.apply(zipped)
val symbol: Symbol = annotatedFields.to[List].find(_.isDefined).get match {
case Some(symbol) => symbol
case _ => throw new Exception(s"Class has no attribute marked with @IdAnnot")
}
println(s"""
|zipped: ${zipped}
|mapped: ${annotatedFields}
|symbol: $symbol
|""".stripMargin)
override def apply(a: A): Long = {
val repr = generic.to(a)
val value = repr.get(Witness(symbol)) // compilation fails here
println(s"""
|Generic ${generic.to(a)}
|value: $value
""".stripMargin)
1
}
}
}
我试图变出 aSelector返回值,但编译器失败并显示No field this.symbol.type in record HL.
我无法让它工作!谢谢