gpt4 book ai didi

scala - 无定型:通过镜盒类别或视场参数化的通用镜片

转载 作者:行者123 更新时间:2023-12-04 03:43:45 26 4
gpt4 key购买 nike

基于:

import shapeless._

case class Content(field: Int)
lens[Content] >> 'field

我正在尝试创建镜头创建方法,例如:
def makeLens[T <: Product](s: Symbol) = lens[T] >> s

但这似乎并不明显。有可能吗?

如果不是这样,我想要达到的最终结果是一种通用的方法,用于更新具有案例类内容的嵌套 map ,例如:
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参数是不可能的。您需要一些额外的隐式参数来跟踪给定名称的单例类型,并提供证据证明它是case类成员的名称:

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, V], 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, V, R <: HList](
outerKey: String,
innerKey: Int,
s: Witness.Aux[K]
)(implicit
gen: LabelledGeneric.Aux[T, R],
sel: Selector.Aux[R, K, V],
upd: Updater.Aux[R, FieldType[K, V], 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"
)

现在让我们定义一个示例 map 和一些镜头:
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

正如您将获得的那样,这与“无样板”有关。困惑的隐式参数列表起初是令人生畏的,但是您很快就习惯了它们,经过一点练习后,它们在收集有关正在使用的类型的不同证据时所起的作用就变得非常直观。

关于scala - 无定型:通过镜盒类别或视场参数化的通用镜片,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25039655/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com