scala – 从案例类中提取给定类型的值
是否可以使用Shapeless从案例类中提取特定类型的值?到目前为止,我可以这样做:
def fromCaseClass[T,R <: HList](value: T)(implicit ga: Generic.Aux[T,R]): R = { ga.to(value) } 然后,这允许我在程序上提取值: scala> case class ServiceConfig(host: String,port: Int,secure: Boolean) defined class ServiceConfig scala> val instance = ServiceConfig("host",80,true) instance: ServiceConfig = ServiceConfig(host,true) scala> fromCaseClass(instance).select[Boolean] res10: Boolean = true scala> fromCaseClass(instance).select[Int] res11: Int = 80 但是,当我尝试编写一个函数来执行此操作时,我会遇到未找到的implicits: def getByType[C,X](value: C)(implicit ga: Generic.Aux[C,X]): X = { fromCaseClass(value).select[X] } <console>:12: error: could not find implicit value for parameter ga: shapeless.Generic.Aux[C,R] fromCaseClass(value).select[X] 据推测我得到的是因为编译器无法验证我的参数不是case类.有没有办法让我这样做? 我对Shapeless很陌生,所以我不能完全确定我是在尝试做一些疯狂的事情还是因为缺少一些简单的东西. 更新 我觉得我离得更近了.我可以这样实现: def newGetByType[C,H <: HList,R] (value: C) (implicit ga: Generic.Aux[C,H],selector: Selector[H,R]): R = { ga.to(value).select[R] } 这允许我从案例类中进行选择: scala> val s: String = newGetByType(instance) s: String = host 但这似乎只适用于case类中的第一个类型: scala> val i: Int = newGetByType(instance) <console>:17: error: type mismatch; found : String required: Int val i: Int = newGetByType(instance) 我是在正确的轨道上吗? 解决方法
你越来越近了……
你的newGetByType的主要问题是它没有给你任何方法来明确指定你希望提取的类型(并且,正如你所观察到的,在LHS上键入val不足以允许它推断). 为什么不能明确指定要提取的类型?这是定义, def getByType[S,C,L <: HList](value: C) (implicit gen: Generic.Aux[C,L],sel: Selector[L,S]): S = gen.to(value).select[S] 理想情况下,我们希望能够指定类型参数S,允许从值参数推断C,并且通过C的隐式解析来计算L.不幸的是,Scala不允许我们部分指定类型争论……这是全有或全无. 因此,使其工作的技巧是将类型参数列表拆分为两个:一个可以完全明确指定,一个可以完全推断:这是一种通用技术,而不是一个特定于无形的技术. 我们通过将计算的主要部分移动到辅助类来完成此操作,该辅助类由我们将明确提供的类型进行参数化, class GetByType[S] { def apply[C,L <: HList](value: C) (implicit gen: Generic.Aux[C,S]): S = gen.to(value).select[S] } 请注意,现在我们可以假设S是已知的,并且可以推断出要应用的两个类型参数.我们完成了现在微不足道的getByType定义,它只提供了显式类型参数可以去的地方,并实例化了辅助类, def getByType[S] = new GetByType[S] 这给你你想要的结果, scala> import shapeless._,ops.hlist._ import ops.hlist._ scala> :paste // Entering paste mode (ctrl-D to finish) class GetByType[S] { def apply[C,S]): S = gen.to(value).select[S] } // Exiting paste mode,now interpreting. defined class GetByType scala> def getByType[S] = new GetByType[S] getByType: [S]=> GetByType[S] scala> case class ServiceConfig(host: String,true) scala> getByType[String](instance) res0: String = host scala> getByType[Int](instance) res1: Int = 80 scala> getByType[Boolean](instance) res2: Boolean = true (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |