scala – 无形:通过case类或字段参数化的通用镜头
发布时间:2020-12-16 09:26:06 所属栏目:安全 来源:网络整理
导读:基于: import shapeless._case class Content(field: Int)lens[Content] 'field 我正在尝试制作镜头创建方法,其中包括: def makeLens[T : Product](s: Symbol) = lens[T] s 但这似乎并不明显.有可能吗? 如果没有,我想要实现的最终结果是用类大小写内容更
基于:
import shapeless._ case class Content(field: Int) lens[Content] >> 'field 我正在尝试制作镜头创建方法,其中包括: def makeLens[T <: Product](s: Symbol) = lens[T] >> s 但这似乎并不明显.有可能吗? 如果没有,我想要实现的最终结果是用类大小写内容更新嵌套映射的通用方法,例如: import scalaz._ import Scalaz._ import PLens._ import shapeless._ import shapeless.contrib.scalaz._ def nestedMapLens[R,T <: Product](outerKey: String,innerKey: Int,f: Symbol) = ~((lens[T] >> f).asScalaz) compose mapVPLens(innerKey) compose mapVPLens(outerKey) 当用T和f参数化时,我无法使它工作.还有其他惯用的无样板解决方案吗? 谢谢! 解决方法
你的makeLens的问题是我们想要的,例如makeLens [Content](‘foo)在编译时失败,而普通的Symbol参数则无法实现.您需要一些额外的隐式参数来跟踪给定名称的单例类型,并提供证据表明它是案例类成员的名称:
import shapeless._,ops.record.{ Selector,Updater },record.FieldType class MakeLens[T <: Product] { def apply[K,V,R <: HList](s: Witness.Aux[K])(implicit gen: LabelledGeneric.Aux[T,R],sel: Selector.Aux[R,K,V],upd: Updater.Aux[R,FieldType[K,R] ): Lens[T,V] = lens[T] >> s } def makeLens[T <: Product] = new MakeLens[T] 接着: scala> case class Content(field: Int) defined class Content scala> makeLens[Content]('field) res0: shapeless.Lens[Content,Int] = shapeless.Lens$$anon$6@7d7ec2b0 但是makeLens [Content](‘foo)将无法编译(这就是我们想要的). 您需要为nestedMapLens进行相同类型的跟踪: import scalaz._,Scalaz._ import shapeless.contrib.scalaz._ case class LensesFor[T <: Product]() { def nestedMapLens[K,R <: HList]( outerKey: String,s: Witness.Aux[K] )(implicit gen: LabelledGeneric.Aux[T,R] ): PLens[Map[String,Map[Int,T]],V] = (lens[T] >> s).asScalaz.partial.compose( PLens.mapVPLens(innerKey) ).compose( PLens.mapVPLens(outerKey) ) } 请注意,我假设build.sbt像这样: scalaVersion := "2.11.2" libraryDependencies ++= Seq( "com.chuusai" %% "shapeless" % "2.0.0","org.typelevel" %% "shapeless-scalaz" % "0.3" ) 现在让我们定义一个示例地图和一些镜头: val myMap = Map("foo" -> Map(1 -> Content(13))) val myFoo1Lens = LensesFor[Content].nestedMapLens("foo",1,'field) val myBar2Lens = LensesFor[Content].nestedMapLens("bar",2,'field) 接着: scala> myFoo1Lens.get(myMap) res4: Option[Int] = Some(13) scala> myBar2Lens.get(myMap) res5: Option[Int] = None 这就像你将要获得的“无样板”一样.凌乱的隐式参数列表一开始是令人生畏的,但是你很快就会习惯它们,并且它们在一些实践后将你正在使用的类型的不同证据集合在一起变得相当直观. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |