如何解决如何在编译时使用 shapeless 将类的名称作为字符串文字获取?
这是一个后续问题:
How to get the name of a case class field as a string/symbol at compile time using shapeless?
假设我要编写一个可以转换产品类型的递归转换器:
case class Prod (
a: Int,b: String
)
into a Record,但与上面使用每个 case 类字段 (a,b) 作为键的问题不同,我想直接使用每个类名或类型/类型构造函数名称。所以这个产品类型在编译时就变成了 Record:
"Int" ->> Int
"String" ->> String
(可能不是一个足够好的用例,但你明白了)
其中一个关键步骤是在编译时使用反射获取每个类的名称,并将它们转换为单例类型或无形见证。我想知道是否已经在某处提供了这种功能?还是我绝对需要一个白盒宏来实现它?
解决方法
你必须写一个宏
import shapeless.ops.hlist.Mapper
import shapeless.{Generic,HList,Poly1,Typeable}
import scala.language.experimental.macros
import scala.reflect.macros.whitebox
trait FieldTypes[A <: Product] {
type Out <: HList
}
object FieldTypes {
type Aux[A <: Product,Out0 <: HList] = FieldTypes[A] { type Out = Out0 }
implicit def mkFieldTypes[A <: Product,L <: HList](implicit
generic: Generic.Aux[A,L],mapper: Mapper[typeablePoly.type,L]
): Aux[A,mapper.Out] = null
object typeablePoly extends Poly1 {
implicit def cse[A](implicit typeable: Typeable[A]): Case[A] = macro cseImpl[A]
def cseImpl[A: c.WeakTypeTag](c: whitebox.Context)(typeable: c.Tree): c.Tree = {
import c.universe._
val str = c.eval(c.Expr[String](c.untypecheck(q"$typeable.describe")))
val tpA = weakTypeOf[A]
q"null.asInstanceOf[FieldTypes.typeablePoly.Case.Aux[$tpA,_root_.shapeless.labelled.FieldType[$str,$tpA]]]"
}
}
}
测试:
import shapeless.{HNil,::}
import shapeless.labelled.FieldType
implicitly[FieldTypes.Aux[Prod,FieldType["Int",Int] :: FieldType["String",String] :: HNil]]
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。