彼らがこの種のもののために作られたので、誰もレンズを加えなかったことはおかしい。だから、ここではその上にCSの背景紙は、あるここではレンズにタッチ簡単にScalaで使うブログです、ここ Scalaz用レンズの実装であり、ここで驚くほどあなたの質問のように見える、それを使用して、いくつかのコードは、です。そして、ボイラープレートを削減するために、ここにあるケースクラスのScalazレンズを生成するプラグイン。
ボーナスポイントについては、レンズに関するその他のSOの質問と、Tony Morrisによる論文をご覧ください。
レンズの大きな問題は、レンズが構成可能であることです。そのため、最初はやや扱いにくいですが、使用するほど地面が増えていきます。また、個々のレンズをテストするだけでよいので、それらはテスト容易性に優れており、当然のことながらそれらの構成を採用できます。
したがって、この回答の最後に提供された実装に基づいて、レンズでこれを行う方法を次に示します。まず、住所の郵便番号と人の住所を変更するようにレンズを宣言します。
val addressZipCodeLens = Lens(
get = (_: Address).zipCode,
set = (addr: Address, zipCode: Int) => addr.copy(zipCode = zipCode))
val personAddressLens = Lens(
get = (_: Person).address,
set = (p: Person, addr: Address) => p.copy(address = addr))
次に、それらを構成して、人の郵便番号を変更するレンズを取得します。
val personZipCodeLens = personAddressLens andThen addressZipCodeLens
最後に、そのレンズを使用してrajを変更します。
val updatedRaj = personZipCodeLens.set(raj, personZipCodeLens.get(raj) + 1)
または、いくつかの構文糖を使用します。
val updatedRaj = personZipCodeLens.set(raj, personZipCodeLens(raj) + 1)
あるいは:
val updatedRaj = personZipCodeLens.mod(raj, zip => zip + 1)
この例で使用されている、Scalazからの簡単な実装を次に示します。
case class Lens[A,B](get: A => B, set: (A,B) => A) extends Function1[A,B] with Immutable {
def apply(whole: A): B = get(whole)
def updated(whole: A, part: B): A = set(whole, part) // like on immutable maps
def mod(a: A, f: B => B) = set(a, f(this(a)))
def compose[C](that: Lens[C,A]) = Lens[C,B](
c => this(that(c)),
(c, b) => that.mod(c, set(_, b))
)
def andThen[C](that: Lens[B,C]) = that compose this
}