Set the portion of the state viewed through the lens and return its new value. */ def assign(b: => B2): IndexedState[A1, A2, B2] = mods(_ => b) /** Set the portion of the state viewed through the lens and return its new value. */ def :=(b: => B2): IndexedState[A1, A2, B2] = assign(b) /** Set the portion of the state viewed through the lens and return its old value. * @since 7.0.2 */ def assigno(b: => B2): IndexedState[A1, A2, B1] = modo(_ => b) /** Set the portion of the state viewed through the lens and return its old value. alias for `assigno` * @since 7.0.2 */ def <:=(b: => B2): IndexedState[A1, A2, B1] = assigno(b) /** Modify the portion of the state viewed through the lens, but do not return its new value. */ def mods_(f: B1 => B2): IndexedState[A1, A2, Unit] = IndexedState(a => (mod(f, a), ())) /** Modify the portion of the state viewed through the lens, but do not return its new value. */ def %==(f: B1 => B2): IndexedState[A1, A2, Unit] = mods_(f) /** Contravariantly map a state action through a lens. */ def lifts[C](s: IndexedState[B1, B2, C]): IndexedState[A1, A2, C] = IndexedState(a => modp(s(_), a)) def %%=[C](s: IndexedState[B1, B2, C]): IndexedState[A1, A2, C] = lifts(s) /** Map the function `f` over the lens as a state action. */ def map[C](f: B1 => C): State[A1, C] = State(a => (a, f(get(a)))) /** Map the function `f` over the value under the lens, as a state action. */ def >-[C](f: B1 => C): State[A1, C] = map(f) /** Bind the function `f` over the value under the lens, as a state action. */ def flatMap[C](f: B1 => IndexedState[A1, A2, C]): IndexedState[A1, A2, C] = IndexedState(a => f(get(a))(a)) /** Bind the function `f` over the value under the lens, as a state action. */ def >>-[C](f: B1 => IndexedState[A1, A2, C]): IndexedState[A1, A2, C] = flatMap[C](f) /** Sequence the monadic action of looking through the lens to occur before the state action `f`. */ def ->>-[C](f: => IndexedState[A1, A2, C]): IndexedState[A1, A2, C] = flatMap(_ => f)
因为State是个Monad,我们可以用for-comprehension来实现行令式编程:
1 nameL run peter //> res6: scalaz.IndexedStore[String,String,Exercises.LensDemo.Person] = Indexe 2 //| dStoreT((<function1>,Peter Chan))
3 cityL run peter.address //> res7: scalaz.IndexedStore[Exercises.LensDemo.City,Exercises.LensDemo.City,E 4 //| xercises.LensDemo.Address] = IndexedStoreT((<function1>,City(ShenZhen,GuangDong)))
5 val updateInfo = for { 6 _ <- ageL += 1
7 zip <- addrL >=> zipL 8 _ <- (addrL >=> zipL) := zip + "A"
9 _ <- nameL %= {n => n + " Junior"} 10 _ <- (addrL >=> cityL) := City("GuangZhou","GuangDong") 11 info <- get
12 } yield info //> updateInfo : scalaz.IndexedStateT[scalaz.Id.Id,Exercises.LensDemo.Person,E 13 //| xercises.LensDemo.Person,Exercises.LensDemo.Person] = scalaz.IndexedStateT$ 14 //| $anon$10@74a10858
15 updateInfo eva l peter //> res8: scalaz.Id.Id[Exercises.LensDemo.Person] = Person(Peter Chan Junior,21 16 //| ,4806111,Address(13 baoan road,40001A,City(GuangZhou,GuangDong)))
这是一段比较典型的行令程序。
上面例子的 += 是NumericLens一项操作。NumericLens是这样定义的:
type NumericLens[S, N] = NumericLensFamily[S, S, N]
val NumericLens: NumericLensFamily.type = NumericLensFamily
/** Allow the illusion of imperative updates to numbers viewed through a lens */
case class NumericLensFamily[S1, S2, N](lens: LensFamily[S1, S2, N, N], num: |