Scala函数式编程课后习题答案(第六章)

本文提供了Scala函数式编程第六章的课后习题答案,包括练习6.1到6.5,详细解答了各个问题。

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)

  //OOP风格
  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
  }

  //FP风格
  def modify[S](f: S => S): State[S,Unit] ={
    for {
      s0 <- getState
      _ <- setState(f(s0))
    }yield ()
  }
  //递归方式实现sequence
  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)} //按照List元素递归处理
      }
    }
    State(s => go(s,xs,List()))
  }
  //右折叠算法实现sequence
  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)(_::_)}
  }
  //左折叠算法实现sequence
  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)(_::_)}
  }


  //FP实现售货机
  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) //关闭状态,投币+1,状态为开启
                case (Turn, Machine(false, nCardy, nCoin)) => Machine(true, nCardy-1, nCoin) //开启状态,旋钮,糖-1,状态为关闭
              }
            }
          }
        }
      }
      s <- getState
    } yield s.coins
  }

  //FP风格提炼逻辑的售货机
  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) //关闭状态,投币+1,状态为开启
        case (Turn, Machine(false, nCardy, nCoin)) => Machine(true, nCardy-1, nCoin) //开启状态,旋钮,糖-1,状态为关闭
      }
    }
    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)))
    //println(simulateMachineFP(inputs).run(Machine(true,3,0)))
    //println(simulateMachineConcise(inputs).run(Machine(true,3,0)))
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值