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, 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] = [email protected]
그러나 makeLens[Content]('foo)
당신은 주어진 이름의 싱글 유형을 추적하고이 경우 클래스의 멤버의 이름이 있다는 증거를 제공하기 위해 몇 가지 추가 암시 인수를 필요 (우리가 원하는) 컴파일되지 않습니다.
scalaVersion := "2.11.2"
libraryDependencies ++= Seq(
"com.chuusai" %% "shapeless" % "2.0.0",
"org.typelevel" %% "shapeless-scalaz" % "0.3"
)
이제
의는 예를 들어지도 및 일부 렌즈를 정의 할 수 있습니다 :이 같은 build.sbt
있으리라 믿고있어
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)
)
}
참고 :
당신은 당신의
nestedMapLens
에 대한 추적의 같은 종류가 필요합니다 :
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
이것은 대략 "상용구없는"것입니다. 지저분한 함축적 인 인수 목록은 처음에는 협박이지만, 익숙해지면 작업하는 유형에 대한 다양한 증거 자료를 모으는 역할이 약간의 연습 후에 상당히 직관적이됩니다.