Scala函数式编程课后习题答案(第六章)
练习6.1,6.2,6.3,6.4,6.5
trait RNG {
def nextInt:(Int,RNG)
}
case class seedRNG(seed:Long) extends RNG{
def nextInt:(Int,RNG)={
val seed2 = (seed*0x5DEECE66DL + 0xBL) & 0xFFFFFFFFFFFFL
((seed2 >>> 16).asInstanceOf[Int],seedRNG(seed2))
}
}
object RNG{
def double(rng:RNG):(Double,RNG) ={
val (i,rng2) = rng.nextInt
if (i == Int.MaxValue) (0.0,rng2)
else (i.toDouble/Int.MaxValue.toDouble,rng2)
}
def nonNegativeInt(rng: RNG): (Int, RNG)={
val (i,rng2) = rng.nextInt
if (i == Int.MaxValue) (Int.MaxValue,rng2)
else (i.abs,rng2)
}
def nextBoolean(rng:RNG):(Boolean,RNG)={
rng.nextInt match {
case (i,rng2) => (i%2==0,rng2)
}
}
def intDouble(rng:RNG):((Int,Double),RNG)={
val (i,rng2)= nonNegativeInt(rng)
val (d,rng3)= double(rng2)
((i,d),rng3)
}
def doubleInt(rng:RNG):((Double,Int),RNG) ={
val (d,rng2) = double(rng)
val (i,rng3) = nonNegativeInt(rng2)
((d,i),rng3)
}
def double3(rng:RNG):((Double,Double,Double),RNG)={
val (d1,rng2)= double(rng)
val (d2,rng3)= double(rng2)
val (d3,rng4)= double(rng3)
((d1,d2,d3),rng4)
}
def ints(count:Int)(rng:RNG):(List[Int],RNG)={
def go(count:Int,rng:RNG,acc:List[Int]):(List[Int],RNG)={
if (count<=0) (acc,rng)
else{
val (i,rng2) = rng.nextInt
go(count-1,rng2,i::acc)
}
}
go(count,rng,Nil:List[Int])
}
type Rand[+A] = RNG =>(A,RNG)
val int:Rand[Int] =_.nextInt
def unit[A](a:A):Rand[A]= rng => (a,rng)
def map[A,B](s:Rand[A])(f: A=>B):Rand[B]={
rng =>{
val (a, rng2) = s(rng)
(f(a),rng2)
}
}
def nonNegativeEven: Rand[Int] = map(nonNegativeInt)(i =>i-i%2)
def double2(rng:RNG):Rand[Double]= {map(nonNegativeInt){ _ /(Int.MaxValue.toDouble+1)}}
}
6.11
/**
* Created by Abbott on 2017/5/27.
*/
object State {
case class State[S,+A](run:S =>(A,S)){
def flatMap[B](f:A => State[S,B]):State[S,B]= State[S,B]{
s =>{
val (a,s1) = run(s)
f(a).run(s1)
}
}
def map[B](f:A => B):State[S,B]= flatMap{a=>unit(f(a))}
def map2[B,C](sb:State[S,B])(f:(A,B)=>C):State[S,C]= flatMap{a=>sb.map{ b=>f(a,b)}}
def map3[B,C,D](sb:State[S,B],sc:State[S,C])(f:(A,B,C)=>D):State[S,D]=flatMap{a=>sb.flatMap{b=>sc.map(c=>f(a,b,c))}}
}
def unit[S,A](a:A) = State[S,A](s =>(a,s))
def getState[S]:State[S,S] = State[S,S]{s => (s,s)}
def setState[S](s:S):State[S,Unit] =State[S,Unit] {_ => ((),s)}
type candy = Int
type coin = Int
sealed trait Input
case object Coin extends Input
case object Turn extends Input
case class Machine(locked:Boolean, candies:Int, coins:Int)
def simulateMachine(inputs:List[Input]):State[Machine,coin]={
def transition(input:Input, machine:Machine):Machine={
(input,machine) match {
case (_, Machine(_,0,_)) => machine
case (Turn, Machine(true,_,_)) => machine
case (Coin, Machine(false,_,_)) => machine
case (Coin, Machine(true,_,nCoin)) => machine.copy(locked = false,coins = nCoin +1)
case (Turn,Machine(false,nCandy,_)) => machine.copy(locked = true,candies = nCandy-1)
}
}
def execute(inputs:List[Input],machine: Machine): Machine= {
inputs match {
case Nil => machine
case h::t => execute(t,transition(h,machine))
}
}
for{
s0 <- getState
_ <- setState(execute(inputs,s0))
s1 <- getState
} yield s1.coins
}
def modify[S](f: S => S): State[S,Unit] ={
for {
s0 <- getState
_ <- setState(f(s0))
}yield ()
}
def sequence[S,A](xs:List[State[S,A]]):State[S,List[A]] ={
def go(s:S, actList:List[State[S,A]], acc:List[A]): (List[A],S) ={
actList match {
case Nil => (acc.reverse,s)
case h::t => h.run(s) match {case (a2,s2) => go(s2,t,a2::acc)}
}
}
State(s => go(s,xs,List()))
}
def sequenceByRight[S,A](xs:List[State[S,A]]):State[S,List[A]] ={
xs.foldRight(unit[S,List[A]](List())){(f,acc) => f.map2(acc)(_::_)}
}
def sequenceByLift[S,A](xs:List[State[S,A]]):State[S,List[A]] ={
xs.reverse.foldLeft(unit[S,List[A]](List())){(acc,f) => f.map2(acc)(_::_)}
}
def simulateMachineFP(inputs:List[Input]):State[Machine,coin]={
for{
_ <- sequenceByLift{
inputs.map{
input => modify{
machine:Machine => {
(input,machine) match {
case (_, Machine(_,0,_)) => machine
case (Turn, Machine(true,_,_)) => machine
case (Coin, Machine(false,_,_)) => machine
case (Coin, Machine(true, nCardy, nCoin)) => Machine(false, nCardy, nCoin+1)
case (Turn, Machine(false, nCardy, nCoin)) => Machine(true, nCardy-1, nCoin)
}
}
}
}
}
s <- getState
} yield s.coins
}
def simulateMachineConcise(inputs:List[Input]):State[Machine,coin]={
def transition(input: Input, machine: Machine): Machine ={
(input,machine) match {
case (_, Machine(_,0,_)) => machine
case (Turn, Machine(true,_,_)) => machine
case (Coin, Machine(false,_,_)) => machine
case (Coin, Machine(true, nCardy, nCoin)) => Machine(false, nCardy, nCoin+1)
case (Turn, Machine(false, nCardy, nCoin)) => Machine(true, nCardy-1, nCoin)
}
}
for{
_ <- sequenceByLift(inputs.map{input =>modify{machine:Machine =>transition(input,machine)}})
s <- getState
} yield s.coins
}
def main(args: Array[String]): Unit = {
val inputs = List(Coin, Turn, Coin, Turn, Turn, Coin, Coin, Coin, Turn)
println(simulateMachine(inputs).run(Machine(true,3,0)))
}
}