trait RNG{
def nextInt: (Int,RNG)
}
case class SimpleRNG(seed: Long) extends RNG{
//返回一个随机Int值,纯函数式实现,返回新的SimpleRNG
def nextInt: (Int,RNG) = {
val newSeed = (seed * 0x5DEECE66DL + 0xBL) & 0xFFFFFFFFL
val nextRNG = SimpleRNG(newSeed)
val n = (newSeed >>> 16).toInt
(n, nextRNG)
}
//带有副作用的实现,currentSeed的更新是隐含的
val currentSeed = seed
def nextInt2: Int = {
val newSeed = (currentTime * 0x5DEECE66DL + 0xBL) & 0xFFFFFFFFL
currentSeed = newSeed
val n = (newSeed >>> 16).toInt
n
}
}
type Rand[+A] = RNG => (A, RNG)
val int: Rand[Int] = _.nextInt
_.nextInt 等价于 RNG => (Int,RNG)
。即接受一个RNG类型参数并返回一个(Int,RNG)类型元组的函数。Rand[Int]
是函数RNG => (Int,RNG)
的类型别名。def map[A,B](s: Rand[A])(f: A => B): Rand[B] =
rng1 => {
val (v,rng2) = s(rng1)
(f(v),rng2)
}
def flatMap[A,B](f: Rand[A)(g: A => Rand[B]): Rand[B] =
rng => {
(v,r) = f(rng)
g(v)(r)
}
def map2[A,B,C](ra: Rand[A], rb: Rand[B])(f: (A,B) => C): Rand[c] =
rng1 => {
val (v1,rng2) = ra(rng1)
val (v2,rng3) = rb(rng2)
(f(v1,v2),rng3)
}
def unit[A](a: A): Rand[A] = rng => (a,rng)
def sequence[A](fs: List[Rand[A]]): Rand[List[A]] =
List.foldRight(fs,unit(List[A())))((x,y) => map2(x,y)((a,b) => Cons(a,b)))
type State[+A,S] = S => (A,S)
case class State[+A,S](run: S => (A,S)) extends AnyVal{
def map[B](f: A => B): State[B,S] = State(
s => {
val (i,r) = run(s)
(f(i),r)
})
def map2[B,C](b: State[B,S])(f: (A,B) => C): State[C,S] = State(
s => {
val (v1,s1) = run(s)
val (v2,s2) = b.run(s1)
(f(v1,v2),s2)
})
//def _map2[B,C](b: State[B,S])(f: (A,B) => C): State[C,S] =
// flatMap(x => b.map(y => f((x,y))))
def flatMap[B](f: A => State[B,S]): State[B,S] = State(
s => {
val (v,s1) = run(s)
f(v).run(s1)
})
}
object State{
def unit[A,S](x: A): State[A,S] = State(s => (x,s))
def sequence[A,S](ls: List[State[A,S]]): State[List[A],S] =
List.foldRight(ls,unit[List[A],S](List()))((x,y) => x.map2(y)(Cons(_,_)))
def modify[S](f: S => S): State[Unit,S] = for {
s <- get //获取当前状态分配给s
_ <- set(f(s)) //设置新状态
} yield ()
def get[S]: State[S,S] = State(s => (s,s))
def set[S](s: S): State[Unit,S] = State(_ => ((), s))
}
EXERCISE 13 (hard): To gain experience with the use of State, implement a simulation of a simple candy dispenser. The machine has two types of input: You can insert a coin, or you can turn the knob to dispense candy. It can be in one of two states: locked or unlocked. It also tracks how many candies are left and how many coins it contains.
[外链图片转存失败(img-Amx9zUUg-1564306192450)(http://oxaz2p2ac.bkt.clouddn.com/Screen Shot 2017-10-04 at 10.21.02 PM.png)]
package PureFunctionalState
import datastruct._
sealed trait Input
case object Coin extends Input
case object Turn extends Input
case class Machine(locked: Boolean, candies: Int, coins: Int) {
/** 有副作用的实现
* 实际上Machine的状态就是自己的属性,所以返回值类型Machine实际上既是值又是状态
* 所以这个实现应该可以看作纯函数式的实现
*/
def simulateMachine(inputs: List[Input]): Machine = {
List.foldLeft(inputs,Machine(locked,candies,coins))((x, y) => (x,y) match {
case (Coin,Machine(true,cands,x)) if cands>0 => Machine(false,cands,x)
case (Turn,Machine(false,cands,x)) if cands>0 => Machine(true,cands-1,x+1)
case _ => y
}
)
}
/** 纯函数式实现。
* modify返回State[Unit,Machine]。modify从旧状态生成新状态,也就是据inputs的每个输入得到一个新的Machine
* map返回List[State[Unit,Machine]]
* sequence返回State[List[Unit],Machine]
*/
def simulateMachine3(inputs: List[Input]): State[(Int, Int),Machine] = for {
_ <- State.sequence(List.map(inputs)(i => State.modify((s: Machine) => (i, s) match {
case (_, Machine(_, 0, _)) => s
case (Coin, Machine(false, _, _)) => s
case (Turn, Machine(true, _, _)) => s
case (Coin, Machine(true, candy, coin)) =>
Machine(false, candy, coin + 1)
case (Turn, Machine(false, candy, coin)) =>
Machine(true, candy - 1, coin)
})))
s <- State.get
} yield (s.candies, s.coins)
}
object TestMachine{
def main(args: Array[String]): Unit = {
val machine = Machine(true,10,0)
val ls = List(Coin,Turn,Turn,Coin,Turn,Coin,Coin,Turn)
println(machine.simulateMachine(ls))
println(machine.simulateMachine3(ls).run(machine))
}
}