scala函数式编程-学习笔记

 

spark&scala:		https://blog.csdn.net/jasonding1354
课后练习		https://www.scala-exercises.org/fp_in_scala/pure_functional_state
Scala 课堂		https://twitter.github.io/scala_school/zh_cn/index.html
==============================================================Scala 函数式编程==============================================================
书中代码:
https://github.com/fpinscala/fpinscala
https://github.com/fpinscala/fpinscala/tree/master/answerkey
scalaAPI文档
https://www.scala-lang.org/api/2.9.1/scala/package.html
https://www.scala-lang.org/api/current/
关于Scala参数传递:	https://www.jianshu.com/p/9b9519a36d78
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++PART 1 函数式编程介绍
=========================================================Chapter 1 什么是函数式编程
//1.1SimpleExample
//1.1.1 一段带有副作用的scala程序
//ex1.1: coffee1
class cafe{
	def buycoffee(cc:creditcard):coffee=
		{val cup=new coffee()
		cc.charge(cup.price)	//此处为副作用:信用卡计费
		cup}
	}
//ex1.2:  +Payments
class cafe{
	def buycoffee(cc:creditcard,p:Payments):coffee=
		{val cup=new coffee()
		p.charge(cc,cup.price)
		cup}
	}

//1.1.2 函数式解法:去除副作用
#通过让buycoffee方法在返回coffee时把charge也作为值一并返回
//把费用和的创建过程和执行过程分离
class cafe{
	def buycoffee(cc:creditcard):(coffee,charge)={
		val cup = new coffee()
		(cup,charge(cc,cup.price))
	}
}
//charge 类
case class charge(cc:creditcard,amount:Double){
	def combine(other:charge):charge=
		if (cc==other.cc) charge(cc,amount+other.amount)
		else throw new Exception("Can't combine chargs to different cards")
}

//ex1.3: 使用buycoffees方法购买多杯咖啡
class cafe{
	def buycoffee(cc:creditcard):(coffee,charge)={val cup = new coffee();(cup,charge(cc,cup.price))}
	def buycoffees(cc:creditcard,n:Int):(List[Coffee],charge)={
		val purchases:List[(coffee,charge)]=List.fill(n)(buycoffee(cc))
		val (coffees,charges)=purchases.unzip
		(coffees,charges.reduce((c1,c2)=>c1.combine(c2)))
	}
	def coalesce(charges:List[charge]):List[charge]=charges.groupBy(_.cc).values.map(_.reduce(_ combine _)).toList
}

//1.2 (纯)函数究竟是什么
#一个函数在函数的执行过程中除了根据输入参数运算结果之外没有其他影响,就可以说没有副作用 则为存函数。
#当调用一个函数时所传入的参数时是引用透明的,并且函数调用也是引用透明的,那么这个函数是一个纯函数。

//1.3 引用透明,纯粹性以及代换模型
class coffee {val price:Int=25;val brand:String="likin"}
class creditcard{def charge(price:Int):Unit={if (price>10) println(">10")}}
def buycoffee(cc:creditcard):coffee={val cup=new coffee();cc.charge(cup.price);cup}
//test
scala> val test =new creditcard
	test: creditcard = creditcard@31daf094

scala> buycoffee(test)
	>10
	res2: coffee = coffee@267309f7


//代换模型
#引用透明要求函数不论进行任何操作都可以用它的返回值来替代
//example1:引用透明的
scala> val x ="hello,zieox"				--->x: String = hello,zieox
scala> val r1=x.reverse					--->r1: String = xoeiz,olleh
scala> val r2=x.reverse					--->r2: String = xoeiz,olleh
scala> val r3="hello,zieox".reverse			--->r3: String = xoeiz,olleh
scala> val r4="hello,zieox".reverse			--->r4: String = xoeiz,olleh
scala> r1==r2						--->res0: Boolean = true
scala> r3==r2						--->res1: Boolean = true
scala> r1==r3						--->res2: Boolean = true
scala> r1==r4						--->res3: Boolean = true
scala> r2==r4						--->res4: Boolean = true
scala> r3==r4						--->res5: Boolean = true

//example2:引用不透明的
scala> val x=new StringBuilder("Hello")			--->x: StringBuilder = Hello
scala> val y=x.append(",zieox")				--->y: StringBuilder = Hello,zieox
scala> val r1=y.toString				--->r1: String = Hello,zieox
scala> val r2=y.toString				--->r2: String = Hello,zieox

scala> val x2=new StringBuilder("Hello")		--->x2: StringBuilder = Hello
scala> val r11=x2.append(",zieox").toString		--->r11: String = Hello,zieox
scala> val r22=x2.append(",zieox").toString		--->r22: String = Hello,zieox,zieox
#在r22调用x.append时,r11已经改变了x引用的对象。


=========================================================Chapter 2 在Scala中使用函数式编程
//2.1 Scala语言介绍:an example
//ex:2.1
object Mymodule {		//object:创建一个新的单例类型
	def abs(n:Int):Int=if (n<0) -n else n
	private def formatAbs(x:Int)={
		val msg = "the Absolute value of %d is %d"
		msg.format(x,abs(x))
	}
	def main(args:Array[String]):Unit=println(formatAbs(-42))
}


//2.2 运行程序
scala /home/lufax/桌面/Sc.scala
//载入代码
:load /home/lufax/桌面/Sc.scala

//2.3 模块,对象和命名空间
import Mymodule.abs
import Mymodule._

//2.4 高阶函数:把函数传给函数
//2.4.1 迂回做法:使用循环方式
//实现一个阶层
def factorial(n:Int):Int={
	def go(n:Int,acc:Int):Int=if (n<=0) acc else go(n-1,n*acc)
	go(n,1)
	}

//exercise:斐波那契
def fib(n:Int):Int= n match {
	case 0 => 0
	case 1 => 1
	case n: Int if(n > 1)=> fib(n - 1) + fib(n - 2)
	case _ => 0
}
	

//2.4.2 第一个高阶函数
object Mymodule2 {
	def abs(n:Int):Int=if (n<0) -n else n
	def factorial(n:Int):Int={			//累乘
		def go(n:Int,acc:Int):Int=if (n<=0) acc else go(n-1,n*acc)
		go(n,1)
	}
	private def formatAbs(x:Int)={
		val msg="The absolute value of %d is %d"
		msg.format(x,abs(x))
	}
	private def formatFactorial(n:Int)={
		val msg="The factorial of %d is %d"
		msg.format(n,factorial(n))
	}
 	def main(args:Array[String]):Unit={
		println(formatAbs(-42))
		println(formatFactorial(7))
	}
	
}


//将formatAbs与formatFactorial 合并为高阶函数formatResult
def formatResult(name:String,n:Int,f:Int=>Int)={
	val msg="the %s of %d is %d"
	msg.format(name,n,f(n))
}

scala> formatResult("abs",-818,abs)					--->res22: String = the abs of -818 is 818
scala> formatResult("factorial",7,fib)					--->res23: String = the factorial of 7 is 13


//2.5 多态函数:基于类型的抽象
//2.5.1 一个多态函数的例子
//ex2.3: 在数组中查找字符串的单态函数
def findFirst(ss:Array[String],key:String):Int={
	def loop(n:Int):Int=if (n>ss.length) -1 else if (ss(n)==key) n else loop(n+1)
	loop(0)
}

//ex2.4: 在数组中查找元素的多态函数
//ex2.4:构建一个多态的泛型函数
def findFirst[A](as:Array[A],p:A=>Boolean):Int={
	def loop(n:Int):Int=if (n>=as.length) -1 else if (p(as(n))) n else loop(n+1)
	loop(0)
}

scala> val a= Array("a","b","c")				--->a: Array[String] = Array(a, b, c)
scala> def f(a:String):Boolean=a=="c"				--->f: (a: String)Boolean
scala> findFirst(a,f)						--->res0: Int = 2

//exercise:2.2 排序函数
def isSorted[A](as: Array[A], gt: (A,A) => Boolean): Boolean = {
	@annotation.tailrec
	def go(n: Int): Boolean =
		if (n >= as.length-1) true
		else if (gt(as(n),as(n+1))) false
		else go(n+1)
	go(0)
}

val a = Array(1,2,3)
def desc(a:Int,b:Int):Boolean=a>b
isSorted(a,(a:Int,b:Int)=>a>b)						--->res5: Boolean = true

//2.5.2 对高阶函数传入匿名函数
scala> findFirst(Array(1,2,5),(x:Int)=>x==9)			--->res9: Int = -1
//在scala中函数也是值
val lessThan=new Function2[Int,Int,Boolean]{def apply(a:Int,b:Int)=a<b}
scala> lessThan.apply(10,10)					--->res11: Boolean = false
scala> lessThan.apply(10,20)					--->res12: Boolean = true


//2.6 通过类型来实现多态
def partial1[A,B,C](a:A,f:(A,B)=>C):B=>C = (b:B)=>f(a,b)

#partial1有3个类型参数A,B,C以及2个参数 返回类型为B=>C
//ex:2.3 科里化
https://blog.csdn.net/onwingsofsong/article/details/77822920
def curry[A,B,C](f:(A,B)=>C):A=>(B=>C) = a=>b=>f(a,b)

//ex:2.4 反科里化
def uncurry[A,B,C](f:A=>B=>C):(A,B)=>C = (a,b)=>f(a)(b)

//ex:2.5 组合函数
def compose[A,B,C](f:B=>C,g:A=>B):A=>C = a => f(g(a))

val f =(x:Double)=>math.Pi / 2-x
val cos = f andThen math.sin
def a[A,B,C](a:A,f:(A,B)=>C):B=>C = (b:B)=>f(a,b)

=========================================================Chapter 3 函数式数据结构
//3.1 定义函数式数据结构
https://github.com/fpinscala/fpinscala
https://blog.csdn.net/nmgrd/article/details/80903401
//ex3.1: 单向链表
package fpinscala.datastructures
sealed trait List[+A]
case object Nil extends List[Nothing]
case class Cons[+A](head: A, tail: List[A]) extends List[A]
object List2{
	def sum(ints:List[Int]):Int=ints match {
		case Nil => 0
		case Cons(x,xs) => x+sum(xs)
	}
	def product(ds:List[Double]):Double=ds match{
		case Nil => 1.0
		case Cons(0.0,_)=>0.0
		case Cons(x,xs)=>x*product(xs)
	}
	def apply[A](as:A*):List[A]=if (as.isEmpty) Nil else Cons(as.head,apply(as.tail:_*))
}

val ex1: List[Double]=Nil
val ex3: List[String]=Cons("a",Cons("b",Nil))
------------------------------------------------tes----------------------------------------------------
在这里不能直接val list 因为此list非彼List
List2.sum(b)--->6
scala> val a = List[Int](1,2,3)				--->a: List[Int] = Cons(1,Cons(2,Cons(3,Nil)))
-------------------------------------------------------------------------------------------------------
//3.2 模式匹配
#scala中的 object:与数据类型同名的一个单例。
//ex:模式匹配
List(1,2,3) match {case _ =>238}
List(1,2,3) match {case Cons(h,_)=>h}

//ex3.1:

val x = List(1,2,3,4,5) match {
	case Cons(x,Cons(2,Cons(4,_)))=>x
	case Nil => 45
	case Cons(x,Cons(y,Cons(3,Cons(4,_))))=>x+y
	case Cons(h,t)=>h+sum(t)
	case _ =>101
}

//scala 中的可变参数
//apply函数:可变
def apply[A](as:A*):List[A]=if (as.isEmpty) Nil else Cons(as.head,apply(as.tail:_*))
scala> apply(1,2,3,543)						--->res8: List[Int] = List(1, 2, 3, 543)
#可变参数A* :接收0或多个类型为A的参数

//3.3 函数式数据结构中的数据共享
//ex3.2: 实现tail
def tail[A](l: List[A]): List[A] =
	l match {
		case Nil => sys.error("tail of empty list")
		case Cons(_,t) => t
	}

//ex3.3:实现setHead
def setHead[A](l: List[A], h: A): List[A] = l match {
	case Nil => sys.error("setHead on empty list")
	case Cons(_,t) => h::t
	}

//rec**
//3.3.1 数据共享的效率
//ex:3.4 实现drop
def drop[A](l: List[A], n: Int): List[A] =
	if (n <= 0) l else l match {
		case Nil => Nil
		case Cons(_, t) => drop(t, n - 1)
	}

//ex:3.5 实现dropWhile
def dropWhile2[A](l:List[A],f:A=>Boolean):List[A] = 
	l match {
		case Cons(h,t) if f(h)=>dropWhile(t,f)
		case _ => l
	}

//ex append
def append[A](a1: List[A], a2: List[A]): List[A] = a1 match {
	case Nil => a2
	case Cons(x, xs) => Cons(x, append(xs, a2))
}

//ex:3.6 实现init
def init2[A](l:List[A]):List[A] = 
l match {
	case Nil => Nil
	case Cons(x, xs) => xs match {
		case Nil => Nil
		case Cons(y, ys) => Cons(x, init(xs))
	}
}


//3.3.2 改进高阶函数的类型推导 P31
def dropWhile[A](l:List[A],f:A=>Boolean):List[A] = 
	l match {
		case Cons(h,t) if f(h)=>dropWhile(t,f)
		case _ => l
	}
val xs:List[Int]=List(1,2,3,4,5)
val ex1=dropWhile(xs,(x:Int)=>x<4)
//改进版
def dropWhile[A](l:List[A])(f:A=>Boolean):List[A] = 
	l match {
		case Cons(h,t) if f(h)=>dropWhile(t)(f)
		case _ => l
	}

val xs:List[Int]=List(1,2,3,4,5)
val ex1=dropWhile(xs,(x:Int)=>x<4)


//3.4 基于list的递归并泛华为高阶函数
def sum2(ints:List[Int]):Int=ints match {
	case Nil => 0
	case Cons(x,xs) => x+sum2(xs)
}
def product2(ds:List[Double]):Double=ds match{
	case Nil => 1.0
	case Cons(x,xs)=>x*product2(xs)
}

//ex3.2:右折叠的简单运用
def foldRight[A,B](as:List[A],z:B)(f:(A,B)=>B):B=
	as match {
		case Nil => z
		case Cons(x,xs) => f(x,foldRight(xs,z)(f))
	}
def sum2(ns:List[Int])=foldRight(ns,0)((x,y)=>x+y)
def product2(ns:List[Double])=foldRight(ns,1.0)(_ * _)

//ex:3.8
*
We get back the original list! Why is that? As we mentioned earlier, one way of thinking about what `foldRight` "does" is it replaces the `Nil` constructor of the list with the `z` argument, and it replaces the `Cons` constructor with the given function, `f`. If we just supply `Nil` for `z` and `Cons` for `f`, then we get back the input list.
	foldRight(Cons(1, Cons(2, Cons(3, Nil))), Nil:List[Int])(Cons(_,_))
	Cons(1, foldRight(Cons(2, Cons(3, Nil)), Nil:List[Int])(Cons(_,_)))
	Cons(1, Cons(2, foldRight(Cons(3, Nil), Nil:List[Int])(Cons(_,_))))
	Cons(1, Cons(2, Cons(3, foldRight(Nil, Nil:List[Int])(Cons(_,_)))))
	Cons(1, Cons(2, Cons(3, Nil)))
*
//ex:3.9 foldRight计算List的长度
def length[A](l:List[A]):Int = foldRight(l,0)((_,acc) => acc + 1)

//ex:3.10 通用列递归foldLeft
def foldLeft[A,B](l:List[A],z:B)(f:(B,A)=>B):B = l match {
	case Nil => z
	case Cons(h,t) => foldLeft(t, f(z,h))(f)
}

//ex:3.11 sum & product & length(by F with foldLeft)
def sum3(l: List[Int]) = foldLeft(l, 0)(_ + _)
def product3(l: List[Double]) = foldLeft(l, 1.0)(_ * _)
def length2[A](l: List[A]): Int = foldLeft(l, 0)((acc,h) => acc + 1)

//ex:3.12 实现reverse
def reverse[A](l:List[A]):List[A]=foldLeft(l,List[A]())((acc,h)=>Cons(h,acc))

//ex:3.13 
def foldRightViaFoldLeft[A, B](l: List[A], z: B)(f: (A, B) => B): B = foldLeft(reverse(l), z)((b, a) => f(a, b))

//ex:3.14
def foldRight[A, B](as: List[A], z: B)(f: (A, B) => B): B =
	as match {
		case Nil => z
		case Cons(x, xs) => f(x, foldRight(xs, z)(f))
} 
@annotation.tailrec
def foldLeft[A, B](l: List[A], z: B)(f: (B, A) => B): B = l match {
	case Nil => z
	case Cons(h, t) => foldLeft(t, f(z, h))(f)
}
def foldRightViaFoldLeft_1[A,B](l:List[A],z:B)(f:(A,B) => B) =foldLeft(l,(b: B) => b)((g,a) => b => g(f(a,b)))(z)
def foldLeftViaFoldRight[A,B](l:List[A],z:B)(f:(B,A) => B): B =foldRight(l,(b: B) => b)((a,g) => b => g(f(b,a)))(z)
def appendViaFoldRight[A](l:List[A],r:List[A]):List[A] =foldRight(l,r)(Cons(_,_))

//ex:3.15
def concat[A](l: List[List[A]]): List[A] = foldRight(l, Nil:List[A])(append)

//3.4.1 更多与列表相关的函数
//ex:3.16 对列表每个元素+1的函数
def add1(l:List[Int]): List[Int] = foldRight(l,Nil:List[Int])((h,t) => Cons(h + 1, t))
//ex:3.17 写一个将List[Double]中每个Double转换成String的函数
def doubleToString(l:List[Double]):List[String] = foldRight(l,Nil:List[String])((h,t) => Cons(h.toString,t))
//ex:3.18 泛化map函数,对列表中每个元素修改,并维持列表结构
def map[A, B](l: List[A])(f: A => B): List[B] = foldRight(l, Nil: List[B])((h, t) => Cons(f(h), t))\
def map_1[A, B](l: List[A])(f: A => B): List[B] = foldRightViaFoldLeft(l, Nil: List[B])((h, t) => Cons(f(h), t))
def map_2[A, B](l: List[A])(f: A => B): List[B] = {
	val buf = new scala.collection.mutable.ListBuffer[B]
	def go(l:List[A]):Unit = l match {
		case Nil => ()
		case Cons(h,t) => buf += f(h); go(t)
	}
	go(l)
	List(buf.toList: _*)
}

//ex:3.19 filter函数,从列表中删除不满足断言的元素,并用它删除一个List[Int]中的所有奇数
def filter[A](l: List[A])(f: A => Boolean): List[A] = foldRight(l, Nil: List[A])((h, t) => if(f(h)) Cons(h, t) else t)
def filter_1[A](l: List[A])(f: A => Boolean): List[A] =foldRightViaFoldLeft(l, Nil: List[A])((h, t) => if(f(h)) Cons(h, t) else t)
def filter_2[A](l: List[A])(f: A => Boolean): List[A] = {
	val buf = new scala.collection.mutable.ListBuffer[A]
	def go(l: List[A]): Unit = l match {
		case Nil => ()
		case Cons(h, t) => if(f(h)) buf += h; go(t)
	}
	go(l)
	List(buf.toList: _*)
}

//ex:3.20 
def flatMap[A, B](l: List[A])(f: A => List[B]): List[B] =concat(map(l)(f))
//ex:3.21 用flatMap实现filter
def filterViaFlatMap[A](l: List[A])(f: A => Boolean): List[A] = flatMap(l)(a => if(f(a)) List(a) else Nil)
//ex:3.22 F(List(1,2,3),List(4,5,6)) => List(5,7,9) 
def addPairWise(a: List[Int], b: List[Int]): List[Int] = (a, b) match {
	case (Nil, _) => Nil
	case (_, Nil) => Nil
	case (Cons(h1, t1), Cons(h2, t2)) => Cons(h1 + h2, addPairWise(t1, t2))
}
//ex:2.23 实现泛化 并命名为zipWith
def zipWith[A,B,C](a:List[A],b:List[B])(f:(A,B) => C): List[C] = (a,b) match {
	case (Nil, _) => Nil
	case (_, Nil) => Nil
	case (Cons(h1,t1),Cons(h2,t2)) => Cons(f(h1,h2),zipWith(t1,t2)(f))
}
@annotation.tailrec
def startWith[A](l: List[A], prefix: List[A]): Boolean = (l,prefix) match {
	case (_, Nil) => true
	case (Cons(h, t), Cons(h2, t2)) if h == h2 => startWith(t, t2)
	case _  => false
}


//标准库中的列表
def take(n:Int):List[A]
def takeWhile(f:A=>Boolean):Boolean
def forall(f:A=>Boolean);Boolean
def exists(f:A=>Boolean):Boolean

//3.4.2 用简单的组件组合list函数时的效率损失
//ex:3.24 p36 F:检测一个List子序列是否包含一个List
def hasSubsequence[A](sup: List[A], sub: List[A]): Boolean = sup match {
	case Nil => sub == Nil
	case _ if startWith(sup, sub) => true
	case Cons(h, t) => hasSubsequence(t, sub)
}

//3.5 树
//Scala中的元组
scala> val p = ("Bob",23)				--->p: (String, Int) = (Bob,23)
scala> p._1						--->res40: String = Bob
scala> p._2						--->res41: Int = 23
scala> p match {case (a,b)=>b}				--->res42: Int = 23

scala> val b=List((1,2),(3,4),(5,6))			--->b: List[(Int, Int)] = List((1,2), (3,4), (5,6))
scala> for(i<-b) i match{ case (a,b)=>println(a+b)}	--->3
						 	    7
//简单的二叉树结构							    11
sealed trait Tree[+A]
case class Leaf[A](value:A) extends Tree[A]
case class Branch[A](left:Tree[A],right:Tree[A]) extends Tree[A]

//ex:3.25 F:统计一棵树中的节点数
def size[A](t: Tree[A]): Int = t match {
	case Leaf(_) => 1
	case Branch(l,r) => 1 + size(l) + size(r)
}
//ex:3.26 F:Max 返回Tree[Int]中最大的元素
def maximum(t: Tree[Int]): Int = t match {
	case Leaf(n) => n
	case Branch(l,r) => maximum(l) max maximum(r)
	}
//ex:3.27 F:返回根节点到任何叶节点最大的路径长度
def depth[A](t: Tree[A]): Int = t match {
	case Leaf(_) => 0
	case Branch(l,r) => 1 + (depth(l) max depth(r))
	}
//ex:3.28 F:map
def map[A,B](t: Tree[A])(f: A => B): Tree[B] = t match {
	case Leaf(a) => Leaf(f(a))
	case Branch(l,r) => Branch(map(l)(f), map(r)(f))
	}
//ex:3.29 泛化size,max,depth和map
def fold[A,B](t: Tree[A])(f: A => B)(g: (B,B) => B): B = t match {
	case Leaf(a) => f(a)
	case Branch(l,r) => g(fold(l)(f)(g), fold(r)(f)(g))
	}
def sizeViaFold[A](t: Tree[A]): Int = fold(t)(a => 1)(1 + _ + _)
def maximumViaFold(t: Tree[Int]): Int = fold(t)(a => a)(_ max _)
def depthViaFold[A](t: Tree[A]): Int = fold(t)(a => 0)((d1,d2) => 1 + (d1 max d2))


//example:
def main(args: Array[String]): Unit = {
    val liStr: List[String]  = List("wo", "shi", "zhong", "guo", "ren", "ni", "shi", "sha", "bi")
    val liStrSub = List("ni", "shi", "sha", "bi")
    println(liStr)
    val hasSubSeq = List.hasSubsequence(liStr, liStrSub)
    println(hasSubSeq)
    val doubleELe = List.map(liStr)((a: String)  => a * 2)
    println(doubleELe)
    val lenGt3 = List.filter(liStr)((a: String) => a.length > 3)
    println(lenGt3)
    println(List.lenght(liStr))
    val liInt = List(1, 2, 3, 4, 5, 6, 7, 8, 9)
    val add1 = List.add1(liInt)
    println(add1)
    println("sum:" + List.sum(liInt))
    println("foldLeft with 1000: " + List.foldLeft(liInt, 1000)(_ + _))
    println(List.reverse(liInt))
    val init = List.init(liInt)
    println("init: " + init)
    val tail = List.tail(liInt)
    println("tail: " + tail)
    val dropLe5 = List.dropWhile(liInt, (a: Int) => a <= 5)
    println(dropLe5)
    val lili = List(List(1, 3, 5, 7), List(2, 4, 6, 8))
    val concated = List.concat(lili)
    println(concated)
    val zipList = List.zipWith(List(1, 3, 5, 7), List(2, 4, 6, 8))((_, _))
    println(zipList)
    val addPair = List.addPairWise(List(1, 2, 3, 4), List(4, 3, 2, 1))
    println(addPair)
    val join = List.foldRightViaFoldLeft(List(1, 3, 5, 7, 9, 11, 13, 15, 17, 19), "")((a: Int, b: String) => b + a.toString)
    println(join)
  }
 
}


=========================================================Chapter 4 不使用异常来处理错误
scala Option方法: http://www.runoob.com/scala/scala-options.html
https://www.jianshu.com/p/c46781f68f80
//4.1 异常的优点与劣势
//ex4.1: 抛出与捕获异常
def failingFn(i:Int):Int={
	val y:Int=throw new Exception("Fail")
	try{val x=42+5 ;x+y}
	catch {case e:Exception=>43}
}
scala> failingFn(1)
	java.lang.Exception: Fail
	  at .failingFn(<console>:12)
	  ... 28 elided

//failingFn2
def failingFn2(i:Int):Int={
	try{val x=42+5;x+((throw new Exception("Fail")):Int)}
	catch{case e:Exception=>43}
}

scala> failingFn2(1)				--->res13: Int = 43
#引用透明的表达式不依赖上下文,非引用透明的表达式依赖上下文。
//异常存在的两个主要问题
1. 异常破坏了引用透明并引入了上下文依赖。
2. 异常不是类型安全的。

//4.2 异常的其他选择
/*def mean(xs:Seq[Double]):Double=
	if (xs.isEmpty) throw new ArithmeticException("mean of empty list!")
	else xs.sum/xs.length*/
def mean_1(xs:IndexedSeq[Double],onEmpty:Double):Double =if (xs.isEmpty) onEmpty else xs.sum/xs.length

//4.3 Option 数据类型
sealed trait Option [+A]
case class Some[+A](get:A) extends Option[A]
case object None extends Option[Nothing]
//ex:mean的Some实现
def mean(xs:Seq[Double]):Option[Double]=if (xs.isEmpty) None else Some(xs.sum/xs.length)

//4.3.1 Option的使用模式
//Scala之Option:
https://blog.csdn.net/bluishglc/article/details/51290759
https://blog.csdn.net/Winterto1990/article/details/52105674
//Option具有更直白的语义:它代表的值可能是一个具体的值,但也可能是空
https://www.jianshu.com/p/95896d06a94d

//基础函数中的Option
//ex:4.2 Option数据类型
trait Option[+A]{
	def map[B](f:A=>B):Option[B]
	def flatMap[B](f:A=>Option[B]):Option[B]
	def getOrElse[B>:A](default: => B): B
	def orElse[B>:A](ob: =>Option[B]):Option[B]	//非必要不对ob求值
	def filter(f:A=>Boolean):Option[A]
}

//ex:4.1 实现Option数据类型
def map[B](f: A => B): Option[B] = this match {
	case None => None
	case Some(a) => Some(f(a))
}
	
def getOrElse[B>:A](default: => B): B = this match {
	case None => default
	case Some(a) => a
}
	
def flatMap[B](f: A => Option[B]): Option[B] = map(f) getOrElse None
def flatMap_1[B](f: A => Option[B]): Option[B] = this match {
	case None => None
	case Some(a) => f(a)
}
	
def orElse[B>:A](ob: => Option[B]): Option[B] = this map (Some(_)) getOrElse ob
	/*Again, we can implement this with explicit pattern matching.*/
def orElse_1[B>:A](ob: => Option[B]): Option[B] = this match {
	case None => ob
	case _ => this
}
	/*This can also be defined in terms of `flatMap`.*/
def filter_1(f: A => Boolean): Option[A] = flatMap(a => if (f(a)) Some(a) else None)
	/* Or via explicit pattern matching. */
def filter(f: A => Boolean): Option[A] = this match {
	case Some(a) if f(a) => this
	case _ => None
}



//example:简单的Option用法
def getAStringMaybe(num: Int): Option[String] = {if ( num >= 0 ) Some("A positive number!") else None}
def printResult(num: Int) = {getAStringMaybe(num) match {case Some(str) => println(str);case None => println("No string!")}}
//ex2
def tes(x:String):Option[String]={x match{case "a"=> Some("hello") case "b" => Some("ok");case _ =>None}}

//基础Option函数的使用
case class Employee(name:String,deparment:String)
def lookupByName(name:String):Option[Employee]=
	val joeDepartment:Option[String]=lookupByName("joe").map(_.department)
					lookupByName("joe").flatMap(_.manager)
					lookupByName("joe").map(_.department).getOrElse("Default Dept")

def mean(xs:Seq[Double]):Option[Double]=if (xs.isEmpty) None else Some(xs.sum/xs.length)
//ex:4.2 F 方差
def variance(xs:Seq[Double]):Option[Double] = mean(xs).map(m=>xs.map(x => Math.pow(x-m, 2)).sum / xs.length)
//map函数式+1
val a = List(1,2,3,4,5)
scala> Some(2.0).map(m=>a.map(i=>i+m))				--->res17: Option[List[Double]] = Some(List(3.0, 4.0, 5.0, 6.0, 7.0))
scala> a.map(_+1)						--->res18: List[Int] = List(2, 3, 4, 5, 6)

//ex:
val dept:String=lookupByName("Joe").map(_.dept).filter(_ !="Accounting").getOrElse("Default Dept")

//4.3.2 Option的组合,提升及面向异常的API的包转
def lift[A,B](f:A=>B):Option[A]=>Option[B] = _ map f
def insuranceRateQuote(age:Int,numberOfSpeedingTickets:Int):Double ...

//ex:4.3 使用Option
def parseInsuranceRateQuote(age:String,numberOfSpeedingTickets:String):Option[Double]={
	val optAge:Option[Int]=try2(age.toInt)
	val optTickets:Option[Int]=try2(numberOfSpeedingTickets.toInt)
	insuranceRateQuote(optAge,optTickets)	//无类型检测 (返回Some(Int)/None not String)
}
def try2[A](a: =>A):Option[A]=try Some(a) catch {case e:Exception=>None}

//ex4.3 泛型函数Map2
def map2[A,B,C](a:Option[A],b:Option[B])(f:(A,B) => C): Option[C] = a flatMap (aa => b map (bb => f(aa, bb)))

def parseInsuranceRateQuote(age:String,numberOfSpeedingTickets:String):Option[Double]={
	val optAge:Option[Int]=try2(age.toInt)
	val optTickets:Option[Int]=try2(numberOfSpeedingTickets.toInt)
	map2(optAge,optTickets)(insuranceRateQuote)
}

//ex:4.4 
/*Here's an explicit recursive version:*/
def sequence[A](a: List[Option[A]]): Option[List[A]] =
	a match {
		case Nil => Some(Nil)
		case h :: t => h flatMap (hh => sequence(t) map (hh :: _))
		}
/*It can also be implemented using `foldRight` and `map2`. The type annotation on `foldRight` is needed here; otherwise Scala wrongly infers the result type of the fold as `Some[Nil.type]` and reports a type error (try it!). This is an unfortunate consequence of Scala using subtyping to encode algebraic data types.*/
def sequence_1[A](a: List[Option[A]]): Option[List[A]] = a.foldRight[Option[List[A]]](Some(Nil))((x,y) => map2(x,y)(_ :: _))


//对列表中每个元素进行解析
def pareInts(a:List[String]):Option[List[Int]]=sequence(a map (i=>try2(i.toInt)))
//ex:4.5 实现F (直接使用map和sequence)
def traverse[A,B](a:List[A])(f:A=>Option[B]):Option[List[B]] =
	a match {case Nil => Some(Nil);case h::t => map2(f(h),traverse(t)(f))(_ :: _)}
def traverse_1[A, B](a: List[A])(f: A => Option[B]): Option[List[B]] = 
	a.foldRight[Option[List[B]]](Some(Nil))((h,t) => map2(f(h),t)(_ :: _))
def sequenceViaTraverse[A](a: List[Option[A]]): Option[List[A]] = traverse(a)(x => x)

//For 推导 (for-comprehension)   for与函数式表达
def map2[A,B,C](a:Option[A],b:Option[B])(f:(A,B) => C): Option[C] = a flatMap (aa=>b map(bb=>f(aa,bb)))
def map2[A,B,C](a:Option[A],b:Option[B])(f:(A,B) => C): Option[C] = for {aa<-a;bb<-b} yield f(aa,bb)

//simple example
val a =(1 to 3).toList
val b =a
val f=(a:Double,b:Double)=>a+b
//函数式推导形式
a flatMap (aa=>b map(bb=>f(aa,bb)))				//a<-aa b<-bb 
//for 推导形式
for {aa<-a;bb<-b} yield f(aa,bb)
	for {aa<-a;bb<-b} println(aa+" : "+bb+" - ") yield f(aa,bb)

//4.4 Either 数据类型
scala标准库:		https://www.scala-lang.org/api/current/index.html#scala.Option
sealed trait Either[+E,+A]
case class Left[+E](value:E) extends Either[E,Nothing]
case class Right[+A](value:A) extends Either[Nothing,A]

def f(i:Int) =if(i == 0) Left("Divide by zero") else Right(24/i)
scala> f(0)					--->res24: Product with Serializable with Either[String,Int] = Left(Divide by zero)
scala> f(1)					--->res25: Product with Serializable with Either[String,Int] = Right(24)

//either的用法示例
//either实现mean函数
def mean(xs:IndexedSeq[Double]):Either[String,Double]=if(xs.isEmpty) Left("mean of empty list") else Right(xs.sum/xs.length)
//either实现div函数
def safeDiv(x:Int,y:Int):Either[Exception,Int]=try Right(x/y) catch{case e:Exception=>Left(e)}
//either实现异常转换
def Try[A](a: =>A):Either[Exception,A]=try Right(a) catch{case e:Exception=>Left(e)}

//ex:4.6 either版本的map,flatMap,orElse,map2
def map[B](f: A => B): Either[E, B] =this match {case Right(a) => Right(f(a));case Left(e) => Left(e)}
def flatMap[EE >: E, B](f: A => Either[EE, B]): Either[EE, B] = this match {case Left(e) => Left(e);case Right(a) => f(a)}
def orElse[EE >: E, AA >: A](b: => Either[EE, AA]): Either[EE, AA] =this match {case Left(_) => b;case Right(a) => Right(a)}
def map2[EE >: E, B, C](b: Either[EE, B])(f: (A, B) => C):Either[EE, C] = for { a <- this; b1 <- b } yield f(a,b1)

//
def parseInsuranceRateQuote(age:String,numberOfSpeedingTickets:String):Either[Exception,Double]=
	for{a<-try2{age.toInt};tickets<-try2{numberOfSpeedingTickets.toInt}} yield insuranceRateQuote(a,tickets)

//ex:4.7 用either实现sequence和traverse
def traverse[E,A,B](es: List[A])(f: A => Either[E, B]): Either[E, List[B]] =
	es match {case Nil => Right(Nil);case h::t => (f(h) map2 traverse(t)(f))(_ :: _)}	
def traverse_1[E,A,B](es: List[A])(f: A => Either[E, B]): Either[E, List[B]] =
	es.foldRight[Either[E,List[B]]](Right(Nil))((a, b) => f(a).map2(b)(_ :: _))	
def sequence[E,A](es: List[Either[E,A]]): Either[E,List[A]] = traverse(es)(x => x)


//ex:4.4 使用Either校验数据
sealed class Name(val value:String)
sealed class Age(val value:Int)
case class Person(name:Name,age:Age)

def mkName(name:String):Either[String,Name]=if(name=="" || name==null) Left("Name is empty!") else Right(new Name(name))
def mkAge(age:Int):Either[String,Age]=if(age<0) Left("Age is out of range") else Right(new Age(age))
def mkPerson(name:String,age:Int):Either[String,Person]=mkName(name).map2(mkAge(age))(Person(_, _))

//ex:4.8
/*
There are a number of variations on `Option` and `Either`. If we want to accumulate multiple errors, a simple approach is a new data type that lets us keep a list of errors in the data constructor that represents failures:
	trait Partial[+A,+B]
	case class Errors[+A](get: Seq[A]) extends Partial[A,Nothing]
	case class Success[+B](get: B) extends Partial[Nothing,B]
	
There is a type very similar to this called `Validation` in the Scalaz library. You can implement `map`, `map2`, `sequence`, and so on for this type in such a way that errors are accumulated when possible (`flatMap` is unable to accumulate errors--can you see why?). This idea can even be generalized further--we don't need to accumulate failing values into a list; we can accumulate values using any user-supplied binary function.
	It's also possible to use `Either[List[E],_]` directly to accumulate errors, using different implementations of helper functions like `map2` and `sequence`.
*/


=========================================================Chapter 5 严格求值和惰性求值 
https://blog.csdn.net/hangscer/article/details/60140728

scala> List(1,2,3,4).map(_ +10).filter(_ %2==0).map(_ * 3)			--->res239: List[Int] = List(36, 42)
//执行链 (跟踪List程序)
--->List(11, 12, 13, 14).filter(_ %2==0).map(_ * 3)
	--->List(12, 14).map(_ * 3)
		--->List(36, 42)

//5.1 严格和非严格函数
非严格求值是函数的一个属性,称一个函数是严格求值的意思是:	这个函数可以选择不对它的一个或多个参数求值。
def square(x:Double):Double=x*x
//典型的非严格求值
scala> false && {println("ok");true}				--->res246: Boolean = false	//只有第一个为true的时候才对第二个求值
scala> true || {println("ok");false}				--->res247: Boolean = true	//如果第一个为false的时候才对第二个求值
val result=if (input.isEmpty) sys.error("empty input") else input
//非严格函数if
def if2[A](cond:Boolean,onTrue:()=>A,onFalse:()=>A):A = if (cond) onTrue() else onFalse()
if2(a<12,()=>println("a"),()=>println("b")) 		// ()=> :  函数字面量语法
//构建无参函数if
def if3[A](cond:Boolean,onTrue: =>A,onFalse: =>A):A = if (cond) onTrue else onFalse
scala> if3(false,sys.error("fail"),3)				--->res258: Int = 3
//
def maybeTwice(b:Boolean,i: =>Int)=if(b) i+i else 0
scala> val x = maybeTwice(true,{println("hi");2+22})
	hi
	hi
	x: Int = 48
//在这个情况下 {println("hi");2+22} 被2次求值 所以副作用首先 pritnln("hi")一次 之后再被执行一次
//改写成惰性的
def maybeTwice(b:Boolean,i: =>Int)={lazy val j=i; if(b) j+j else 0}
scala> val x = maybeTwice(true,{println("hi");2+22})		//通过设置lazy 延迟变量的求值,直到第一次被引用的时候
	hi
	x: Int = 48
#scala中非严格求值的函数接收的参数是传名参数,而非传值参数。

*Scala的关键字Lazy:https://www.cnblogs.com/qingyunzong/p/8869761.html
//5.2 一个扩展的例子:惰性列表
//ex5.2:Stream的简单定义
sealed trait Stream[+A]
case object Empty extends Stream[Nothing]
case class Cons[+A](h: ()=>A,t: ()=>Stream[A]) extends Stream[A]

object Stream{
	def cons[A](hd: =>A,tl: =>Stream[A]):Stream[A]={
		lazy val head = hd
		lazy val tail = tl
		Cons(()=>head,()=>tail)
	}
	def empty[A]: Stream[A]=Empty
	def apply[A](as:A*):Stream[A]=if(as.isEmpty) empty else cons(as.head,apply(as.tail:_*))
}

def headOption:Option[A] = this match {
	case Empty=>None
	case Cons(h,t)=>Some(h())
}

//5.2.1 对Stream保持记忆,避免重复运算
#我们希望能缓存Cons节点的值,一旦它们被强制求值。如果我们直接用Cons数据构造器,比如下面的代码,实际上运算了2次expensive(x):
val x=Cons(()=>expensive(x),t1)
val h1=x.headOption
val h2=x.headOption

#通常定义更智能(smart)的构造器来避免这个问题,智能smart构造器的写法习惯上与普通的数据构造器相似,但受首字母小写(cons)。
这里cons构造器负责将传名参数纪录到head和tail,它确保thunk只运行一次。后续调用会返回已缓存的 lazy val。 
def cons[A](hd: =>A,t1: =>Stream[A]):Stream[A]={
	lazy val head=hd
	lazy val tail=t1
	Cons(()=>head,()=>tail)
}
//智能构造器apply
def apply[A](as:A*):Stream[A]= if(as.isEmpty) empty else cons(as.head,apply(as.tail:_*))


//5.2.2 用于检验Stream的helper函数
//ex:5.4 实现toList
def toList: List[A] = {
	@annotation.tailrec
	def go(s: Stream[A], acc: List[A]): List[A] = s match {
		case Cons(h,t) => go(t(), h() :: acc)
		case _ => acc
	}
	go(this, List()).reverse
}

def toListFast: List[A] = {
	val buf = new collection.mutable.ListBuffer[A]
	@annotation.tailrec
	def go(s: Stream[A]): List[A] = s match {
		case Cons(h,t) =>
			buf += h()
			go(t())
		case _ => buf.toList
	}
	go(this)
}
// The natural recursive solution
def toListRecursive: List[A] = this match {
	case Cons(h,t) => h() :: t().toListRecursive
	case _ => List()
}

//ex:5.2 实现take & drop
def take(n: Int): Stream[A] = this match {
	case Cons(h, t) if n > 1 => cons(h(), t().take(n - 1))
	case Cons(h, _) if n == 1 => cons(h(), empty)
	case _ => empty
}

final def drop(n: Int): Stream[A] = this match {
	case Cons(_, t) if n > 0 => t().drop(n - 1)
	case _ => this
}

//ex:5.3 实现takewhile
def takeWhile(f: A => Boolean): Stream[A] = this match {
	case Cons(h,t) if f(h()) => cons(h(), t() takeWhile f)
	case _ => empty
}

//5.3 把函数的描述与求值分离
函数式编程的主题之一是关注分离(separation of concerns)。
希望将计算的描述与实际运行分离。比如一等函数,捕获函数体内的运算逻辑,只有在接收到参数时才去执行它。
使用Option捕获的错误,而决定对它做什么是一个分离的关注点。对于Stream,可以构建一个产生一系列元素的计算逻辑直到实际需要这些元素时才去运行。 
一般而言,惰性化对一个表达式分离了它的描述和求值。 
例如,函数exists检查了Stream中是否存在元素满足某个条件: 
sealed trait Stream[+A]{
	import Stream._
	def exists(p:A =>Boolean):Boolean=this match{
		case Cons(h,t)=>p(h()) || t().exists(p)
		case _=>false
}

注意||对它的第二个参数是非严格求值。如果p(h())返回true,则提前终止遍历。另外,Stream的tail也是lazy val,不仅仅提前终止,而且tail压根没有被求值。 
exits用了显式的递归。还可以以更通用的foldRight方式来实现递归:
def foldRight[B](z: =>B)(f:(A, =>B)=>B):B=this match{
	case Cons(h,t)=>f(h(),t().foldRight(z)(f))
	case _=>z
}

与List的foldRight相似,组合函数f对它的第二个参数(=>B)是非严格求值(传名)。
如果f选择不对第二个参数求值,则提前终止遍历。以下是用foldRight实现的exists函数: 
def exists(p:A=>Boolean):Boolean = foldRight(false)((a,b)=>p(a)||b)


//ex:5.4 实现forall
def forAll(f: A => Boolean): Boolean = foldRight(true)((a,b) => f(a) && b)

//ex:5.5 使用foldRight实现takeWhile
def takeWhile_1(f: A => Boolean): Stream[A] = foldRight(empty[A])((h,t) => if (f(h)) cons(h,t) else empty)

//ex:5.6 使用foldRight实现headOption
def headOption: Option[A] = foldRight(None: Option[A])((h,_) => Some(h))

//ex:5.7 
def map[B](f: A => B): Stream[B] = foldRight(empty[B])((h,t) => cons(f(h), t))
def filter(f: A => Boolean): Stream[A] = foldRight(empty[A])((h,t) => if (f(h)) cons(h, t) else t)
def append[B>:A](s: => Stream[B]): Stream[B] = foldRight(s)((h,t) => cons(h,t))
def flatMap[B](f: A => Stream[B]): Stream[B] = foldRight(empty[B])((h,t) => f(h) append t)


//跟踪Stream程序
//Stream(1,2,3,4).map(_+10).filter(_%2==0).toList该程序的分步解读: 
Stream(1,2,3,4).map(_ +10).filter(_ % 2 ==0).toList
cons(11,Stream(2,3,4).map(_ +10)).filter(_ % 2 ==0).toList
Stream(2,3,4).map(_ +10).filter(_ % 2 ==0).toList
cons(12,Stream(3,4).map(_ +10)).filter(_ % 2 ==0).toList
12 :: Stream(3,4).map(_ +10).filter(_ % 2 ==0).toList
12 :: Cons(13,Stream(4).map(_ +10)).filter(_ % 2 ==0).toList
12 :: Stream(4).map(_ +10).filter(_ % 2 ==0).toList
12 :: Cons(14,Stream().map(_ +10)).filter(_ % 2 ==0).toList
12 :: 14 :: Stream().map(_ +10).filter(_ % 2 ==0).toList
12 :: 14 :: List()
用于生成单个元素的map函数与用于测试元素是否被2整除的filter函数之间交替进行。
并不会完全实例化map运算结果的中间Stream,Stream亦可描述为”一等循环“(first-class loops)。这是Stream转换的增量性质(incremental)。

def find(p:A=>Boolean):Option[A]=filter(p).headOption


//5.4 无限流与共递归
val ones:Sream[Int]=Stream.cons(1,ones)
println(ones.take(3).toListRecursive)
ones.exists(_ %2==1)
ones.map(_ +1).exists(_ %2==0) 
ones.takeWhile(_ ==1)
ones.forAll(_ !=1)

//ex:5.8 实现constant函数,根据定值返回一个无限流
def constant[A](a: A): Stream[A] = {
	lazy val tail: Stream[A] = Cons(() => a, () => tail)
	tail
}

//ex:5.9 写一个函数生成无限流,从n开始,n+1,n+2 ...等
def from(n:Int):Stream[Int]=cons(n, from(n+1))

//ex:5.10 fib无限流函数
val fibs = {
	def go(f0: Int, f1: Int): Stream[Int] =
	cons(f0, go(f1, f0+f1))
	go(0, 1)
}

//ex:5.11 写一个更通用的构造流函数
def unfold[A,S](z:S)(f:S => Option[(A,S)]): Stream[A] =
	f(z) match {
		case Some((h,s)) => cons(h,unfold(s)(f))
		case None => empty
	}
//ex:5.12 根据unfold函数实现fibs,from,constant和ones
val fibsViaUnfold = unfold((0,1)) { case (f0,f1) => Some((f0,(f1,f0+f1))) }
def fromViaUnfold(n: Int) = unfold(n)(n => Some((n,n+1)))
def constantViaUnfold[A](a: A) = unfold(a)(_ => Some((a,a)))
// could also of course be implemented as constant(1)
val onesViaUnfold = unfold(1)(_ => Some((1,1)))

//ex:5.13 根据unfold函数实现map,take,takeWhile,zipWith,zip,zipAll,ZipWithAll
def mapViaUnfold[B](f: A => B): Stream[B] =
	unfold(this) {
		case Cons(h,t) => Some((f(h()), t()))
		case _ => None
	}
	
def takeViaUnfold(n: Int): Stream[A] =
	unfold((this,n)) {
		case (Cons(h,t), 1) => Some((h(), (empty, 0)))
		case (Cons(h,t), n) if n > 1 => Some((h(), (t(), n-1)))
		case _ => None
	}
	
def takeWhileViaUnfold(f: A => Boolean): Stream[A] =
	unfold(this) {
		case Cons(h,t) if f(h()) => Some((h(), t()))
		case _ => None
	}
	
def zipWith[B,C](s2: Stream[B])(f: (A,B) => C): Stream[C] =
	unfold((this, s2)) {
		case (Cons(h1,t1), Cons(h2,t2)) => Some((f(h1(), h2()), (t1(), t2())))
		case _ => None
	}

// special case of `zipWith`
def zip[B](s2: Stream[B]): Stream[(A,B)] = zipWith(s2)((_,_))
def zipAll[B](s2: Stream[B]): Stream[(Option[A],Option[B])] = zipWithAll(s2)((_,_))
def zipWithAll[B, C](s2: Stream[B])(f: (Option[A], Option[B]) => C): Stream[C] =
	Stream.unfold((this, s2)) {
		case (Empty, Empty) => None
		case (Cons(h, t), Empty) => Some(f(Some(h()), Option.empty[B]) -> (t(), empty[B]))
		case (Empty, Cons(h, t)) => Some(f(Option.empty[A], Some(h())) -> (empty[A] -> t()))
		case (Cons(h1, t1), Cons(h2, t2)) => Some(f(Some(h1()), Some(h2())) -> (t1() -> t2()))
	}

//ex:5.14 实现startsWith
def startsWith[A](s:Stream[A]):Boolean = zipAll(s).takeWhile(!_._2.isEmpty) forAll {case (h,h2) => h == h2}

//ex:5.15 实现tails 
def tails: Stream[Stream[A]] =
	unfold(this) {
		case Empty => None
		case s => Some((s, s drop 1))
	} append Stream(empty)

//ex:5.16 把tails泛化为scanRight函数
def scanRight[B](z:B)(f:(A, => B) => B): Stream[B] =
	foldRight((z, Stream(z)))((a, p0) => {
	// p0 is passed by-name and used in by-name args in f and cons. So use lazy val to ensure only one evaluation...
		lazy val p1 = p0
		val b2 = f(a, p1._1)(b2, cons(b2, p1._2))
	})._2


=========================================================Chapter 6 纯函数式
//6.1 以副作用方式生成随机数
//ex6.1: 使用scala.util.Random生成随机数
val r=new scala.util.Random
r.nextDouble
r.nextDouble
r.nextInt
r.nextInt(10)		//随机生成一个0~9的随机Int数

val v = (for (i<-1 to 10) yield r.nextDouble.formatted("%.2f")).toList
val v = (for (i<-1 to 100) yield r.nextInt(10)).toList.count(s=>s.length==4)

def counts(a:List[Int])={
	val counts=scala.collection.mutable.Map.empty[Int,Int]
	for (r<-a){
		val oldcount=if (counts.contains(r)) counts(r) else 0
		counts += (r->(oldcount + 1))
	}
	counts
}

//ex:生成骰子
def rollDie:Int={
	val rng=new scala.util.Random
	rng.nextInt(6)			//生成一个0~5的随机数
}
// 将随机数生成器传给方法
def RollDie(rng:scala.util.Random):Int=rng.nextInt(6)

//6.2 纯函数随机数生成器
trait RNG {def nextInt:(Int,RNG)}	//nextInt特质 函数nextInt接受(Int,RNG)

//ex6.2:一个纯函数式随机数生成器
case class SimpleRNG(seed:Long) extends RNG{
	def nextInt:(Int,RNG)={
		val newSeed=(seed*0x5DEECE66DL+0xBL) & 0xFFFFFFFFFFFFL		//随机数种子
		val nextRNG=SimpleRNG(newSeed)					//通过种子生成新nextRNG
		val n=(newSeed >>> 16).toInt
		(n,nextRNG)							//生成(Int,RNG)
	}
}

scala> val r=SimpleRNG(42)			--->r: SimpleRNG = SimpleRNG(42)
scala> val (n1,r2)=r.nextInt
						--->n1: Int = 16159453
						    r2: RNG = SimpleRNG(1059025964525)
scala> val (n2,r3)=r2.nextInt			--->n2: Int = -1281479697
						    r3: RNG = SimpleRNG(197491923327988)
//6.3 用纯函数式实现带状态的API
//ex
class Foo {
	private var s:FooState = ...
	def bar: Bar
	def bax: Baz
}
//把bar和baz翻译成纯函数式API
trait Foo{def bar:(Bar,Foo);def baz:(Int,Foo)}
//生成一个随机对
def randomPair(rng:SimpleRNG):(Int,Int)={
	val (i1,_)=rng.nextInt
	val (i2,_)=rng.nextInt
	(i1,i2)				//这是随机数seed一样所以i1和i2的值是一样的
}
//不同的i1,i2实现
def randomPair2(rng:RNG):((Int,Int),RNG)={
	val (i1,rng2)=rng.nextInt
	val (i2,rng3)=rng2.nextInt
	((i1,i2),rng3)
}

https://blog.csdn.net/dlke03/article/details/72650417?utm_source=blogxgwz8
//ex:6.1 实现一个nonNegativeInt(输出值非负)
def nonNegativeInt(rng: RNG): (Int, RNG)={
	val (i,rng2) = rng.nextInt
	if (i == Int.MaxValue) (Int.MaxValue,rng2) else (i.abs,rng2)
}

//ex:6.2 实现Double 0~1
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)
}

//ex:6.3 实现(Int,Double) (Double,Int) (Double,Double,Double)
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)
}


//6.4 状态行为的更好的API
//对RNG状态行为数据类型定义一个类型别名(type alias)
type Rand[+A] = RNG=>(A,RNG)		//Rand[+A] 随机生成A类型值的类型
//把RNG的nextInt方法变成新类型的一个值
val int:Rand[Int]=_.nextInt
//写一个组合子组合Rand行为,避免显示地传递RNG状态
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)}
			       s:Rand[A] = rng => (A,rng) ---> s(rng)=(A,rng) 
				 Rand[B] = rng => (B,rng)  
//nonNegativeEven复用nonNegativeInt生成一个大于0并能被2整除的整数
def nonNegativeEven: Rand[Int]=map(nonNegativeInt)(i => i - i%2)

//ex:6.5
def double2(rng:RNG):Rand[Double]= {map(nonNegativeInt){ _ /(Int.MaxValue.toDouble+1)}}


//6.4.1 组合状态行为
//ex:6.6 
def map2[A,B,C](ra:Rand[A],rb:Rand[B])(f: (A,B)=>C):Rand[C] = 
	rng => {
		val (a,r1) = ra(rng)
		val (b,r2) = rb(r1)
		(f(a,b),r2)
		}
//用map2 实现both,randIntDouble,randDoubleInt
def both[A,B](ra:Rand[A],rb:Rand[B]):Rand[(A,B)]=map2(ra,rb)((_, _))
val randIntDouble:Rand[(Int,Double)]=both(int,double)
val randDoubleInt:Rand[(Double,Int)]=both(double,int)

//ex:6.7 实现sequence
def sequence[A](fs:List[Rand[A]]): Rand[List[A]] = fs.foldRight(unit(List[A]()))((f,acc) => map2(f,acc)(_ :: _))

//6.4.2 嵌套状态行为
def nonNegativeLessThan(n:Int):Rand[Int]=
	map(nonNegativeInt) {
		i=>
		val mod=i%n
		if(i+(n-1)-mod>=0) mod else nonNegativeLessThan(n)(???)
	}
//通过显示传递的方法替代map
def nonNegativeLessThan(n:Int):Rand[Int]={
	rng =>
		val (i,rng2) = nonNegativeInt(rng)
		val mod = i % n
		if (i + (n-1) - mod >=0) (mod,rng2) else nonNegativeLessThan(n)(rng)
}

//ex:6.8 实现flatMap
def flatMap[A,B](f:Rand[A])(g:A=>Rand[B]):Rand[B] =
	rng => {
		val (a,r1) = f(rng)
		g(a)(r1)
	}

//ex:6.9 用flatMap实现map和map2
//实现rollDie并修正错误
def rollDie:Rand[Int]=nonNegativeLessThan(6)
val zero=rollDie(SimpleRNG(5))._1
def rollDie:Rand[Int]=map(nonNegativeLessThan(6))(_ + 1)

//6.5 更通用的状态行为数据类型
def map[S,A,B](a:S=>(A,S))(f:A=>B):S=>(B,S)
type State[S,+A] = S=>(A,S)
case class State[S,+A](run:S=>(A,S))
//把Rand作为State的别名
type Rand[A]=State[RNG,A]

//ex:6.10 泛化unit,map,flatMap,map2,sequence
def unit[S, A](a: A): State[S, A] = State(s => (a, s))
def map[B](f: A => B): State[S, B] = flatMap(a => unit(f(a)))
def flatMap[B](f: A => State[S, B]): State[S, B] = State(s => {val (a, s1) = run(s);f(a).run(s1)})
def map2[B, C](sb: State[S, B])(f: (A, B) => C): State[S, C] = flatMap(a => sb.map(b => f(a, b)))
def sequence[S, A](sas: List[State[S, A]]): State[S, List[A]] = sas.foldRight(unit[S, List[A]](List()))((f, acc) => f.map2(acc)(_ :: _))


//6.6 纯函数式命令编程
val ns: Rand[List[Int]]=int.flatMap(x=>int.flatMap(y=>ints(x).map(xs=>xs.map(_ % y))))
val ns: Rand[List[Int]]= for {
	x<-int
	y<-int
	xs<-ints(x)} yield xs.map(_ % y)

def modify[S](f:S=>S):State[S,Unit] = for { s<-get; _ <-set(f(s)) } yield ()
def get[S]:State[S,S]=State(s=>(s,s))
def set[S](s:S):State[S,Unit]=State(_ => ((),s))

//ex: 6.11
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)))
  }
}



=========================================================Chapter 7 纯函数式并行计算
//7.1 选择数据类型和函数
def sum(ints:Seq[Int]):Int=ints.foldLeft(0)((a,b)=>a+b)
//ex7.1:通过分治算法求一列整数的和
def sum(ints:IndexedSeq[Int]):Int = {
	if(ints.size<=1) ints.headOption getOrElse 0 
	else { val (a,b)=ints.splitAt(ints.length/2); sum(a)+sum(b)}
}
val ids=IndexedSeq[Int](1,2,3,4)
scala> sum(ids)						--->res175: Int = 10

//7.1.1 一种用于并行计算的数据类型
def unit[A](a: =>A):Par[A]	//Par(Parallel)
def get[A](a:Par[A]): A

//ex7.2: 用自定义数据类型更新求和算法
def sum(ints:IndexedSeq[Int]):Int = {
	if(ints.size<=1) ints.headOption getOrElse 0 
	else {
		val (l,r)=ints.splitAt(ints.length/2)
		val sumL: Par[Int] = Par.Unit(sum(l))
		val sumR: Par[Int] = Par.Unit(sum(r))
		Par.get(sumL)+Par.get(sumR)
	}
import java.lang.Thread
trait Runnable(r:Runnable){
	def start:Unit		//开始在一个独立线程中运行r
	def join:Unit		//阻塞当前线程直到r运行结束
}
//直接使用原生并发
import java.util.concurrent.Future
class ExecutorService{def submit[A](a:Callable[A]):Future[A]}
trait Future[A]{def get:A}

//7.1.2 组合并行计算 P82
def sum(ints:IndexedSeq[Int]):Int = {
	if(ints.size<=1) Par.unit(ints.headOption getOrElse 0) 
	else { val (a,b)=ints.splitAt(ints.length/2); Par.map2(sum(l),sum(r))(_ + _)}
}

//实现Par.map2
def map2[A,B,C](a:Par[A],b:Par[B])(f:(A,B) => C):Par[C] 

//7.1.3 显性分流
//创建分流,将Par分配到一个独立的逻辑线程中运行
def fork[A](a: =>Par[A]):Par[A]
def sum(ints:IndexedSeq[Int]):Int = {
	if(ints.size<=1) Par.unit(ints.headOption getOrElse 0) 
	else { val (a,b)=ints.splitAt(ints.length/2); Par.map2(Par.fork(sum(l)),Par.fork(sum(r)))(_ + _)}
}
//unit和fork的组合实现
def unit[A](a:A):Par[A]
def unit[A](a: =>A):Par[A]
def lazyUnit[A](a: =>A):Par[A]=>fork(unit(a))


//7.2 确定表现形式
//ex: Par的API草稿
def unit[A](a:A):Par[A]						//将一个恒定值变为一个并行计算
def map2[A,B,C](a:P[A],b:P[B])(f: (A,B)=>C):Par[C]		//合并2个并行计算为一个新的并行计算
def fork[A](a: =>Par[A]):Par[A]					//并发计算,实际上不求值,直到run被调用
def lazyUnit[A](a: =>A):Par[A]=>fork(unit(a))			//包装一个标记为并发的未求值计算
def run[A](a:Par[A]):A						//从实际执行的计算中获取结果值
//
import java.util.concurrent.TimeUnit
import java.util.concurrent.ExecutorService
abstract class ExecutorService {def submit[A](a:Callable[A]):Future[A]}
trait Callable[A]{def call:A}
trait Future[A]{
	def get:A
	def get(timeout:Long,unit:TimeUnit):A
	def cancel(evenIfRunning:Boolean):Boolean
	def isDone:Boolean
	def isCancelled:Boolean
}

def run[A](s:ExecutorService)(a:Par[A]):A
--->直接返回 Future[A]
type Par[A] = ExecutorService => Future[A]
def run[A](s:ExecutorService)(a:Par[A]):Future[A]=a(s)

//7.3 完善API P7.3
//ex:7.5 Par的基本实现 
object Par{
	def unit[A](a:A):Par[A]=(es:ExecutorService)=>UnitFuture(a)
	private case class UnitFuture[A](get:A) extends Future[A]{
 		def isDone=true
		def get(timeout:Long,units:TimeUnit)=get
		def isCancelled=false
		def cancel(eventIfRunning:Boolean):Boolean=false
	}
	def map2[A,B,C](a:Par[A],b:Par[B])(f:(A,B)=>C):Par[C] = 
		(es:ExecutorService)=>{
				val af = a(es)
				val bf = b(es)
				UnitFuture(f(af.get,bf.get))
		}
	def fork[A](a: =>Par[A]):Par[A] = es =>es.submit(new Callable[A]{def call=a(es).get})
}

//ex:7.3 改进map2的实现以支持超时设置
/* This version respects timeouts. See `Map2Future` below. */
def map2[A,B,C](a:Par[A],b:Par[B])(f:(A,B) => C): Par[C] =
	es => {
		val (af,bf) = (a(es),b(es))
		Map2Future(af,bf,f)}

/*Note: this implementation will not prevent repeated evaluation if multiple threads call `get` in parallel.
 We could prevent this using synchronization, but it isn't needed for our purposes here (also, repeated evaluation of pure values won't affect results).*/
case class Map2Future[A,B,C](a: Future[A], b: Future[B],f: (A,B) => C) extends Future[C] {
	@volatile 
	var cache: Option[C] = None
	def isDone = cache.isDefined
	def isCancelled = a.isCancelled || b.isCancelled
	def cancel(evenIfRunning: Boolean) = a.cancel(evenIfRunning) || b.cancel(evenIfRunning)
	def get = compute(Long.MaxValue)
	def get(timeout: Long, units: TimeUnit): C = compute(TimeUnit.NANOSECONDS.convert(timeout, units))
	private def compute(timeoutInNanos: Long): C = cache match {
		case Some(c) => c
		case None =>
			val start = System.nanoTime
			val ar = a.get(timeoutInNanos, TimeUnit.NANOSECONDS)
			val stop = System.nanoTime;val aTime = stop-start
			val br = b.get(timeoutInNanos - aTime, TimeUnit.NANOSECONDS)
			val ret = f(ar, br)
			cache = Some(ret)
			ret
	}
}


//7.4 使用lazyUnit写一个函数将令一个函数A=>B转换为一个异步计算
def asyncF[A,B](f: A => B): A => Par[B] = a => lazyUnit(f(a))
//实现list排序
def sortPar(parList:Par[List[Int]]):Par[List[Int]]=map2(parList,unit(()))((a,_)=>f(a))
def map(parList:Par[List[Int]])=map(parList)(_.sorted)
def parMap[A,B](ps:List[A])(f:A=>B):Par[List[B]]


//ex:7.5 实现sequence函数
def sequence_simple[A](l: List[Par[A]]): Par[List[A]] =l.foldRight[Par[List[A]]](unit(List()))((h,t) => map2(h,t)(_ :: _))
	// This implementation forks the recursive step off to a new logical thread,
	// making it effectively tail-recursive. However, we are constructing
	// a right-nested parallel program, and we can get better performance by
	// dividing the list in half, and running both halves in parallel.
	// See `sequenceBalanced` below.
def sequenceRight[A](as: List[Par[A]]): Par[List[A]] =
	as match {
		case Nil => unit(Nil)
		case h :: t => map2(h, fork(sequenceRight(t)))(_ :: _)
	}
// We define `sequenceBalanced` using `IndexedSeq`, which provides an efficient function for splitting the sequence in half.
def sequenceBalanced[A](as: IndexedSeq[Par[A]]): Par[IndexedSeq[A]] = fork {
	if (as.isEmpty) unit(Vector())
	else if (as.length == 1) map(as.head)(a => Vector(a))
	else {
		val (l,r) = as.splitAt(as.length/2)
		map2(sequenceBalanced(l), sequenceBalanced(r))(_ ++ _)
	}
}
	
def sequence[A](as: List[Par[A]]): Par[List[A]] = map(sequenceBalanced(as.toIndexedSeq))(_.toList)


//ex:7.6 实现parFilter,并行过滤元素
def parFilter[A](l:List[A])(f: A => Boolean): Par[List[A]] = {
	val pars: List[Par[List[A]]] = l map (asyncF((a: A) => if (f(a)) List(a) else List()))
	map(sequence(pars))(_.flatten) // convenience method on `List` for concatenating a list of lists
}

//7.4 API与代数
//7.4.1 映射法则
def equal[A](e:ExecutorService)(p:Par[A],P2:Par[A]):Boolean = p(e).get == p2(e).get
map(unit(x))(f) == unit(f(x))

//7.4.2 分流法则P91
//7.4.3 打破法则:一个微妙的bug P92
//不同的fork实现
def fork[A](fa: =>Par[A]):Par[A] = es=>fa(es)
def delay[A](FA: =>Par[A]):Par[A] = es=>fa(es)

//7.4.4 用Actor实现一个完全无阻塞的Par
//ex7.6: 实现run
import java.util.concurrent.atomic
def run[A](es:ExecutorService)(p:Par[A]): A={
	val ref = new AtomicReference[A]
	val latch = new CountDownLatch(1)
	p(es){a=>ref.set(a);latch.countDown}
	latch.await
	ref.get
}

//ex:创建Par例子 
def unit[A](a:A):Par[A] = es => new Future[A]{def apply(cb: A=>Unit):Unit=cb(a)}
def fork[A](A: =>Par[A]): Par[A] = es=>new Future[A]{def apply(cb: A=>Unit):Unit = eval(es)(a(es)(cb))}
def eval(es:ExecutorService)(r: =>Unit) = es.submit(new Callable[Unit] {def call=r})
def map2[A,B,C](a:Par[A],b:Par[B])(f:(A,B)=>C):Par[C]

//通过Actor实现MAP2
//ex7.7: 用Actor实现MAP2
def map2[A,B,C](p:Par[A],p2:Par[B])(f:(A,B)=>C):Par[C] = 
	es => new Future[C]{
		def apply(cb:C=>Unit):Unit={
			var ar:Option[A]=None
			var br:Option[B]=None
			val combiner = Actor[Either[A,B]](es){
				case Left(a) => br match{
					case None => ar=Some(a)
					case Some(b) => eval(es)(cb(f(a,b)))
				}
				case Right(b) => br match {
					case None => br=Some(b)
					case Some(a) => eval(es)(cb(f(a,b)))
				}
			}
			p(es)(a=>combiner ! Left(a))
			p2(es)(b=>combiner ! Right(b))
		}
	}

import java.util.concurrent.Executors
val p = ParMap(List.range(1,10000))(math.sqrt(_))
val x = run(Executors.newFixedThreadPool(2))(p)


//7.5 完善组合子为更通用的形式
def choice[A](cond:Par[Boolean])(t:Par[A],f:Par[A]):Par[A] = es => if (run(es)(cond).get) t(es) else f(es)

//ex:7.11 实现choiceN
def choiceN[A](n: Par[Int])(choices: List[Par[A]]): Par[A] =
	es => {
		val ind = run(es)(n).get // Full source files
		run(es)(choices(ind))
	}

def choiceViaChoiceN[A](a: Par[Boolean])(ifTrue: Par[A], ifFalse: Par[A]): Par[A] = choiceN(map(a)(b => if (b) 0 else 1))(List(ifTrue, ifFalse))

//ex:7.12 实现choiceMap
def choiceMap[K,V](key: Par[K])(choices: Map[K,Par[V]]): Par[V] =
	es => {
		val k = run(es)(key).get
		run(es)(choices(k))
	}

//ex:7.13 
def chooser[A,B](p: Par[A])(choices: A => Par[B]): Par[B] =
	es => {
		val k = run(es)(p).get
		run(es)(choices(k))
	}
	
/* `chooser` is usually called `flatMap` or `bind`. */
def flatMap[A,B](p: Par[A])(choices: A => Par[B]): Par[B] =
	es => {
		val k = run(es)(p).get
		run(es)(choices(k))
	}
	
def choiceViaFlatMap[A](p: Par[Boolean])(f: Par[A], t: Par[A]): Par[A] = flatMap(p)(b => if (b) t else f)
def choiceNViaFlatMap[A](p: Par[Int])(choices: List[Par[A]]): Par[A] = flatMap(p)(i => choices(i))




=========================================================Chapter 8 基于性质的测试
//8.1 基于性质测试概览
//ScalaCheck特质
val intList=Gen.listOf(Gen.choose(0,100))
val prop=
	forAll(intList)(ns=>ns.reverse.reverse == ns.reverse.lastOption) &&
	forAll(intList)(ns=>ns.headOption == ns.reverse==ns)
val failingProp=forAll(intList)(ns=>ns.reverse == ns)

//8.2 选择数据类型和函数
//8.2.1 API初始代码片段
//8.2.2 性质的含义与API
trait Prop{
	def check:Unit
	def &&(p:prop): Prop = ???
}

//ex:8.3 实现 && 方法 
def &&(p: Prop): Prop = new Prop {def check = Prop.this.check && p.check}

trait Prop{def check:Either[???,SuccessCount]}
object Prop{
	type FailedCase=String
	type SuccessCount=Int
}
trait Prop{def check:Either[(FailedCase,SuccessCount),SuccessCount]}

//8.2.3 生成器的意义和API
//ex:8.4 实现choose
def choose(start: Int, stopExclusive: Int): Gen[Int] = Gen(State(RNG.nonNegativeInt).map(n => start + n % (stopExclusive-start)))
/* We could write this as an explicit state action, but this is far less convenient, since it requires us to manually thread the `RNG` through the computation. */
def choose2(start: Int, stopExclusive: Int): Gen[Int] = Gen(State(rng => RNG.nonNegativeInt(rng) match {case (n,rng2) => (start + n % (stopExclusive-start), rng2)}))

//ex:8.5 实现unit,boolean,;istOfN
def unit[A](a: => A): Gen[A] = Gen(State.unit(a))
def boolean: Gen[Boolean] = Gen(State(RNG.boolean))
def choose(start: Int, stopExclusive: Int): Gen[Int] = Gen(State(RNG.nonNegativeInt).map(n => start + n % (stopExclusive-start)))
def listOfN[A](n: Int, g: Gen[A]): Gen[List[A]] = Gen(State.sequence(List.fill(n)(g.sample)))


//8.2.4 生成值决定生成器
//ex:8.6 实现flatMap => listOfN 
def flatMap[B](f: A => Gen[B]): Gen[B] = Gen(sample.flatMap(a => f(a).sample))
/* A method alias for the function we wrote earlier. */
def listOfN(size: Int): Gen[List[A]] = Gen.listOfN(size, this)
/* A version of `listOfN` that generates the size to use dynamically. */
def listOfN(size: Gen[Int]): Gen[List[A]] = size flatMap (n => this.listOfN(n))

//ex:8.7 实现union
def union[A](g1: Gen[A], g2: Gen[A]): Gen[A] = boolean.flatMap(b => if (b) g1 else g2)
//ex:8.8 实现weighted 
def weighted[A](g1: (Gen[A],Double), g2: (Gen[A],Double)): Gen[A] = {
	val g1Threshold = g1._2.abs / (g1._2.abs + g2._2.abs)
	Gen(State(RNG.double).flatMap(d => if (d < g1Threshold) g1._1.sample else g2._1.sample))
}

//8.2.5 具化Prop的数据类型
trait Prop{def check:Either[(FailedCase,SuccessCount),SuccessCount]}

//ex8.2: 创建一个Result数据类型
sealed trait Result{def isFalsified:Boolean}
case object Passed extends Result{def isFalsified = false}
case class Falsified(failure:FailedCase,success:SuccessCount) extends Result{def isFalsified=true}

//ex8.3: 实现forAll
def forAll[A](as:Gen[A])(f:A=>Boolean):Prop=Prop{
	(n,rng) => randomStream(as)(rng).zip(Stream.from(0)).taken(n).map{
		case (a,i) => try{if (f(a)) Passed else Falsified(a.toString,i)}
			      catch {case e:Exception => Falsified(buildMsg(a,e),i)}
		}.find(_.isFalsified).getOrElse(Passed)
	}
def randomStream[A](g:Gen[A])(rng:RNG):Stream[A]=Stream.unfold(rng)(rng=>Some(g.sample.run(rng)))
def buildMsg[A](s:A,e:Exception):String=
	s"test case: $s\n"+
	s"generated am exception: ${e.getMessage}\n"+
	s"stack trace:\n ${e.getStackTrace.mkString{"\n"}}"

//ex:8.9 实现 && 和 ||
def &&(p: Prop) = Prop {
	(max,n,rng) => run(max,n,rng) match {
		case Passed => p.run(max, n, rng)
		case x => x
	}
}

def ||(p: Prop) = Prop {
	(max,n,rng) => run(max,n,rng) match {
		case Falsified(msg, _) => p.tag(msg).run(max,n,rng)
		case x => x
	}
}

def tag(msg: String) = Prop {
	(max,n,rng) => run(max,n,rng) match {
		case Falsified(e, c) => Falsified(msg + "\n" + e, c)
		case x => x
	}
}


//8.3 最小化测试用例
case class SGen[+A](forSize:Int => Gen[A])	//定长生成器
//ex:8.10 实现 f: Gen -> SGen
def unsized: SGen[A] = SGen(_ => this)
//ex:8.11 基于Gen实现的SGen 
case class SGen[+A](g: Int => Gen[A]) {
	def apply(n: Int): Gen[A] = g(n)
	def map[B](f: A => B): SGen[B] = SGen { g(_) map f }
	def flatMap[B](f: A => SGen[B]): SGen[B] = {
		val g2: Int => Gen[B] = n => {g(n) flatMap { f(_).g(n) }}
		SGen(g2)
	}
	def **[B](s2: SGen[B]): SGen[(A,B)] = SGen(n => apply(n) ** s2(n))
}
//ex:8.12 实现listOf组合子
def listOf[A](g: Gen[A]): SGen[List[A]] = SGen(n => g.listOfN(n))

//ex8.4: 逐渐生成测试用例直到给定最大值
type MaxSize = Int 
case class Prop(run: (MaxSize,TestCases,RNG)=>Result)
def forAll[A](g:SGen[A])(f: A=>Boolean):Prop = forAll(g())(f)
def forAll[A](g: Int=>Gen[A])(f:A=>Boolean):Prop=Prop{
	(max,n,rng) =>
		val casePerSize = (n+(max - 1)) / max
		val props:Stream[Prop]= Stream.from(0).take((n min max)+1).map(i=>forAll(g(i))(f))
		val prop:Prop=props.map(p=>Prop{(max, _,rng)=>p.run(max,casePerSize,rng)}).toList.reduce(_ && _)
		prop.run(max,n,rng)
}

//8.4 使用库并改进其易用性
//8.4.1 一些简单的例子
val smallInt=Gen.choose(-10,10)
val maxProp=forAll(listOf(smallInt)){ns=> val max=ns.max ; !ns.exists(_ > max)}

//ex8.5: 运行Prop的帮助函数
def run(p:Prop,maxSize:Int=100,testCases:Int=100,rng: RNG = RNG.Simple(System.currentTimeMillis)):Unit=
p.run(maxSize,testCases,rng) match {
	case Falsified(msg,n) => println(s"! Falsified after $n passed tests:\n $msg")
	case Passed => println(s"+OK,passed $testCases tests")
}

//ex:8.13 实现listOf1
def listOf1[A](g: Gen[A]): SGen[List[A]] = SGen(n => g.listOfN(n max 1))
val maxProp1 = forAll(listOf1(smallInt)) { l => 
	val max = l.max
	!l.exists(_ > max) // No value greater than `max` should exist in `l`
}

//ex:8.14 实现f: 验证List.sorted
val sortedProp = forAll(listOf(smallInt)) { ns =>
	val nss = ns.sorted
	(nss.isEmpty || nss.tail.isEmpty || !nss.zip(nss.tail).exists {case (a,b) => a > b})
	&& !ns.exists(!nss.contains(_))
	&& !nss.exists(!ns.contains(_))
}

//8.4.2 为并行计算编写测试套件
map(unit(1))(_ +1) ==unit(2)
val ES: ExecutorService=Executors.newCachedThreadPool
val p1 = Prop.forAll(Gen.unit(Par.unit(1)))(i=>Par.map(i)(_ +1)(ES).get == Par.unit(2)(ES).get)

//证明性质 P113
def check(p: =>Boolean): Prop=Prop{(_, _, _)=>if (p) Passed else Falsified}

//ex8.6: 使用run返回Provedobject
def run(p:Prop,maxSize:Int=100,testCases:Int=100,rng: RNG = RNG.Simple(System.currentTimeMillis)):Unit=
	p.run(maxSize,testCases,rng) match {
		case Falsified(msg,n) => println(s"! Falsified after $n passed tests:\n $msg")
		case Passed => println(s"+OK,passed $testCases tests")
		case Proved => println(s"+OK,proved property")
}


//测试PAR
val p2 = Prop.check{
	val p=Par.map(Par.unit(1))(_ +1)
	val p2=Par.unit(2)
	p(ES).get==p2(ES).get
}

def equal[A](p:Par[A],p2:Par[A]):Par[Boolean]=Par.map2(p,p2)(_ == _)
val p3= check{equal(Par.map(Par.unit(1))(_ +1),Par.unit(2))(ES).get}

val S=weighted(choose(1,4).map(Executors.newFixedThreadPool)-> .75,unit(Executors.newCachedThreadPool)->.25)
def forAllPar[A](g:Gen[A])(F:A=>Par[Boolean]):Prop=forAll(S.map2(g)((_,_))){case (s,a)=>f(a)(s).get}

//引入一个**抽取器
def forAllPar[A](g:Gen[A])(f:A=>Par[Boolean]):Prop=forAll(S**g){case (s,a)=>f(a)(s).get}
def forAllPar[A](g:Gen[A])(f:A=>Par[Boolean]):Prop=forAll(S**g){case s**a=>f(a)(s).get}

object ** {def unapply[A,B](p:(A,B))=Some(p)}
val p2=checkPar{ equal(Par.map(Par.unit(1))(_ +1),Par.unit(2))}

//ex:8.16 实现一个Par[Int]的富生成器
val pint2: Gen[Par[Int]] = choose(-100,100).listOfN(choose(0,20))
	.map(l => l.foldLeft(Par.unit(0))((p,i) => Par.fork { Par.map2(p, Par.unit(i))(_ + _) }))
//ex:8.17 fork(x) == x
val forkProp = Prop.forAllPar(pint2)(i => equal(Par.fork(i), i)) tag "fork"

//8.5 测试高阶函数及展望未来
//当测试高阶函数的时候,我们能做的是用具体的参数来验证
val isEven = (i:Int) => i%2==0
val takeWhileProp=Prop.forAll(Gen.listOf(int))(ns=>ns.takeWhile(isEven).forall(isEven))
def genStringIntFn(g:Gen[Int]):Gen[String=>Int]=g map(i=>(s=>i))

//ex:8.19 
https://github.com/fpinscala/fpinscala/blob/master/answerkey/testing/19.answer.markdown
//ex:8.20  P117

//8.6 生成器法则
def map[A,B](a:Par[A])(f:A=>B):Par[B]
def map[B](f:A=>B):Gen[B]


=========================================================Chapter 9 语法分析器组合子
//9.1 代数设计
trait Parser[ParseError,Parser[+_]]{
	def run[A](p:Parser[A])(input:String):Either[ParseError,A]
	def char(c:Char):Parser[Char] 
}

//ex9.1 为Parser支持中缀语法
trait Parsers[ParseError,Parser[+_]]{
	def run[A](p:Parse[A])(input:String):Either[ParseError,A]
	def char(c:Char):Parser[Char] 
	def or[A](s1:Parser[A],s2:Parser[A]):Parser[A]
	implicit def string(s:String):Parser[String]
	implicit def operators[A](p:Parser[A])=ParserOps[A](p)
	implicit def asStringParser[A](a:A)(implicit f:A=>Parser[String]):ParserOps[String]=ParserOps(f(a))
	case class ParserOps[A](p:Parser[A]){
		def | [B>:A](p2:Parser[B]):Parser[B]=self.or(p,p2)
		def or [B>:A](p2: =>Parser[B]):Parser[B]=self.or(p,p2)
	}
}

//9.2 一种可能的代数
def many[A](p:Parser[A]):Parser[List[A]]
def map[A,B](a:Parser[A])(f:A=>B):Parser[B]
map(many(char('a')))(_.size)
val numA: Parser[Int]=char('a').many.map(_.size)
map(p)(a=>a)==p		//结构保持

//ex9.2: 组合Parser与map
trait Parsers[ParseError,Parser[+_]]{
	def run[A](p:Parse[A])(input:String):Either[ParseError,A]
	def char(c:Char):Parser[Char] 
	def or[A](s1:Parser[A],s2:Parser[A]):Parser[A]
	implicit def string(s:String):Parser[String]
	implicit def operators[A](p:Parser[A])=ParserOps[A](p)
	implicit def asStringParser[A](a:A)(implicit f:A=>Parser[String]):ParserOps[String]=ParserOps(f(a))
	case class ParserOps[A](p:Parser[A]){
		def | [B>:A](p2:Parser[B]):Parser[B]=self.or(p,p2)
		def or [B>:A](p2: =>Parser[B]):Parser[B]=self.or(p,p2)
	}
	object Laws{
		def equal[A](p1:Parser[A],p2:Parser[A])(in: Gen[String]):Prop=forAll(in)(s => run(p1)(s) == run(p2)(s))
		def mapLaw[A](p:Parser[A])(in: Gen[String]):Prop=equal(p,p.map(a=>a))(in)
	}
}

//用map实现char & succeed
def char(c:Char):Parser[Char]=string(c.toString) map (_.charAt(0))
def succeed[A](a:A):Parser[A]=string("") map (_ => a)

//9.2.1 切片和非空重复
def many1[A](p:Parser[A]):Parser[List[A]]
def product[A,B](p:Parser[A],p2:Parser[B]):Parser[(A,B)]
//ex:9.1 实现map2
def map2[A,B,C](p:Parser[A],p2:Parser[B])(f:(A,B)=>C):Parser[C]=map(product(p, p2))(f.tupled)
def many1[A](p: Parser[A]): Parser[List[A]] = map2(p, many(p))(_ :: _)

//ex:9.2 总结product的法则
//`product` is associative. These two expressions are "roughly" equal:
(a ** b) ** c
a ** (b ** c)
//The only difference is how the pairs are nested. The `(a ** b) ** c` parser returns an `((A,B), C)`, whereas the `a ** (b ** c)` returns an `(A, (B,C))`. We can define functions `unbiasL` and `unbiasR` to convert these nested tuples to flat 3-tuples:
def unbiasL[A,B,C](p: ((A,B), C)): (A,B,C) = (p._1._1, p._1._2, p._2)
def unbiasR[A,B,C](p: (A, (B,C))): (A,B,C) = (p._1, p._2._1, p._2._2)
//With these, we can now state the associativity property:
(a ** b) ** c map (unbiasL) == a ** (b ** c) map (unbiasR)
//We'll sometimes just use `~=` when there is an obvious bijection between the two sides:、
(a ** b) ** c ~= a ** (b ** c)
//`map` and `product` also have an interesting relationship--we can `map` either before or after taking the product of two parsers, without affecting the behavior:
a.map(f) ** b.map(g) == (a ** b) map { case (a,b) => (f(a), g(b)) }
//For instance, if `a` and `b` were both `Parser[String]`, and `f` and `g` both computed the length of a string, it doesn't matter if we map over the result of `a` to compute its length, or whether we do that _after_ the product.
See chapter 12 for more discussion of these laws.
//x:9.3 用 or,map2,succeed实现many
def many[A](p: Parser[A]): Parser[List[A]] = map2(p, many(p))(_ :: _) or succeed(List())
//ex:9.4 用map2和succeed实现listOfN
def listOfN[A](n:Int,p:Parser[A]):Parser[List[A]] = if (n <= 0) succeed(List()) else map2(p,listOfN(n-1, p))(_ :: _)


//9.3 处理上下文的相关性
//ex:9.6 使用flatMap和其他组合子 实现一个新的原语regex能够分析数字(字符串s可以通过s.r变成一个Regex对象)
for {
	digit <- "[0-9]+".r
	val n = digit.toInt // we really should catch exceptions thrown by toInt and convert to parse failure
	_ <- listOfN(n, char('a'))
} yield n

//ex:9.7 使用flatMap实现product和map2
def product[A,B](p:Parser[A],p2: =>Parser[B]): Parser[(A,B)] = flatMap(p)(a => map(p2)(b => (a,b)))
def map2[A,B,C](p:Parser[A], p2: =>Parser[B])(f:(A,B)=>C): Parser[C] = for { a <- p;b <- p2 } yield f(a,b)

//ex:9.8 使用flatMap和其他组合子实现map
def map[A,B](p: Parser[A])(f: A => B): Parser[B] = p.flatMap(a => succeed(f(a)))


//9.4 写一个JSON分析器
//9.4.1 JSON格式
{ "people": [
{ "firstName": "Brett", "lastName":"McLaughlin", "email": "aaaa" },
{ "firstName": "Jason", "lastName":"Hunter", "email": "bbbb"},
{ "firstName": "Elliotte", "lastName":"Harold", "email": "cccc" }
]}

trait JSON
object JSON {
	case object TNull extends JSON
	case class JUnumber(get: Double) extends JSON
	case class JString(get: String) extends JSON
	case class JBool(get: Boolean) extends JSON
	case class JArray(get: IndexedSeq[JSON]) extends JSON
	case class JObject(get: Map[String,JSON]) extends JSON
	def jsonParser[Parser[+_]](P: Parsers[Parser]): Parser[JSON] = {
		import P.{string => _, _}
		implicit def tok(s: String) = P.token(P.string(s))
		def array = surround("[", "]")(value sep "," map (vs => JArray(vs.toIndexedSeq))) scope "array"
		def obj = surround("{", "}")(keyval sep "," map (kvs => JObject(kvs.toMap))) scope "object"
		def keyval = escapedQuoted ** (":" *> value)
		def lit = scope("literal") {"null".as(JNull) | double.map(JNumber(_)) | escapedQuoted.map(JString(_))
					|"true".as(JBool(true)) |"false".as(JBool(false))}
		def value: Parser[JSON] = lit | obj | array 
			root(whitespace *> (obj | array))
  	}
}
//9.4.2 JSON分析器 P130 
//9.5 错误提示
//9.5.1 一种可行的设计
def label[A](msg:String)(p:Parser[A]):Parser[A]
case class Location(input:String,offset:Int=0){
	lazy val line = input.slice(0,offset+1).count(_ == '\n')+1
	lazy val col = input.slice(0,offset+1).lastIndexOf('\n') match {
		case -1 => offset + 1
		case lineStart => offset - lineStart
	}
}
def errorLocation(e:ParseError):Location
def errorMessage(e:ParseErroe):Location

def labelLaw[A](p:Parser[A],inputs:SGen[String]):Prop = 
	forAll(inputs ** Gen.string) {case (input,msg) =>
			run(label(msg)(p))(input) match{
				case Left(e) => errorMessage(e) == msg
				case _ => true
			}
	}

//9.5.2 错误嵌套
val p = label("first magic word")("abra") ** " ".many ** label("second magic word")("cadabra")
def scope[A](msg:String)(p:Parser[A]):Parser[A]
case class ParserError(stack:List[(Location,String)])

//9.5.3 控制分支和回溯轨迹
//ex:9.11 
def furthest[A](p: Parser[A]): Parser[A]
def latest[A](p: Parser[A]): Parser[A]

//9.6 实现代数
//9.6.1 一种可能的实现
def string(s:String): Parser[A]
def run[A](p:Parser)(input:String):Either[ParseError,A]
def Parser[+A]=String => Either[ParserError,A]
def string(s:String):Parser[A]=(input:String)=>if (input.startsWith(s)) Right(s) else Left(Location(input).toError("Excepted: "+s))
def toError(msg:String):ParseE

//9.6.2 串化分析器
type Result[+A]= Location => Result[A]
trait Result[A]
case class Success[+A](get:A,charsConsumed:Int) extends Result[A]
case class Failure(get:ParseError) extends Result[Nothing]

//9.6.3 标记分析器
//引入push函数
def push(loc:Location,msg:String):ParseError = copy(stack = (loc,msg) :: stack)
//实现scope
def scope[A](msg:String)(p:Parser[A]):Parser[A]= s=> p(s).mapError(_.push(s.loc,msg))
//Result函数上的mapError
def mapError(f:ParseError=>ParseError):Result[A]=this match {
	case Failure(e) =>Failure(f(e))
	case _ => this
}
// 实现label
def label[A](msg:String)(p:Parser[A]):Parser[A]= s => p(s).mapError(_.label(msg))
def label[A](s:String):ParseError=ParserError(latestLoc.map((_,s)).toList)
def latestLoc:Option[Location] = latest map (_._1)
def latest:Option[(Location,String)] = stack.lastOption

//9.6.4 故障转移和回溯
case class Failure(get:ParseError,isCommitted:Boolean) extends Result[Nothing]
def attempt[A](p:Parser[A]):Parser[A] = a => p(s).uncommit
def uncommit:Result[A]=this match{
	case Failure(e,true)=>Failure(e,false)
	case _ => this 
}
//实现or
def or[A](x:Parser[A],y: =>Parser[A]):Parser[A]=
	s => x(s) match{
		case Failure(e,false) => y(s)
		case r => r
}

//9.6.5 上下文相关的分析
//ex9.3: 使用addCommit确保分析器被提交
def flatMap[A,B](f:Parser[A])(G: A=>Parser[B]):Parser[B]=
	s=>f(s) match {
		case Success(a,n)=>g(a)(s.advanceBy(n)).addCommit(n != 0).advanceSuccess(n)
		case e@Failure(_,_)=>e
	}
def advanceBy(n,Int):Location=copy(offset=offset+n)
def addCommit(isCommitted:Boolean):Result[A]=this match{
	case Failure(e,c)=>Failure(e,c || isCommitted)
	case _ => this
}
def advanceSuccess(n:Int):Result[A]=this match{
	case Success(a,m)=>Success(a,n+m)
	case _ => this 
}

//ex:9.15 
def run[A](p: Parser[A])(s: String): Either[ParseError, A] = {
	val s0 = ParseState(Location(s))
	p(s0).extract
}
//ex:9.16 尝试格式化ParseError
case class ParseError(stack: List[(Location,String)] = List()) {
	def push(loc: Location, msg: String): ParseError =copy(stack = (loc,msg) :: stack)
	def label[A](s: String): ParseError =ParseError(latestLoc.map((_,s)).toList)
	def latest: Option[(Location,String)] = stack.lastOption
	def latestLoc: Option[Location] = latest map (_._1)
// Display collapsed error stack - any adjacent stack elements with the same location are combined on one line.
// For the bottommost error, we display the full line, with a caret pointing to the column of the error.
override def toString =
	if (stack.isEmpty) "no error message"
	else {
	val collapsed = collapseStack(stack)
	val context =
		collapsed.lastOption.map("\n\n" + _._1.currentLine).getOrElse("") +
		collapsed.lastOption.map("\n" + _._1.columnCaret).getOrElse("")
	collapsed.map { case (loc,msg) => loc.line.toString + "." + loc.col + " " + msg }.mkString("\n") + context
	}
// Builds a collapsed version of the given error stack - messages at the same location have their messages
// merged, separated by semicolons.
def collapseStack(s: List[(Location,String)]): List[(Location,String)] =
	s.groupBy(_._1).
	mapValues(_.map(_._2).mkString("; ")).
	toList.sortBy(_._1.offset)
def formatLoc(l: Location): String = l.line + "." + l.col

//ex:9.18
// We'll just give a sketch here. The basic idea is to add an additional field to `ParseError`
case class ParseError(stack: List[(Location, String)] = List(),otherFailures: List[ParseError] = List()) {
	def addFailure(e: ParseError): ParseError =this.copy(otherFailures = e :: this.otherFailures)
	// ...
}

// We then need to make sure we populate this in the implementation of `or`
def or[A](p: Parser[A], p2: => Parser[A]): Parser[A] =
	s => p(s) match {
		case Failure(e, false) => p2(s).mapError(_.addFailure(e))
		case r => r // committed failure or success skips running `p2`
}

Part3 函数式设计的通用结构
=========================================================CP10 Monoid(幺半群)
//10.1 什么时Monoid
//IN SHORT:一个Monoid是一个类型,一个此类型的二元操作(满足结合律)和一个单位元元素(zero)
//满足结合律&同一律
op(op(x,y),z)==op(x,op(y,z))		//满足交换律
op(x,zero)==x | op(zero,x)==x		//op零为其本身

trait Monoid[A]{
	def op(a1:A,a2:A):A	//满足op(op(x,y),z)==op(x,op(y,z))
	def zero:A		//满足op(x,zero)==x & op(zero,x)==x
}
val stringMonoid=new Monoid[String]{
	def op(a1:String,a2:String)=a1+a2
	def zero=""
}
def listMonoid[A]=new Monoid[List[A]]{
	def op(a1:List[A],a2:List[A])=a1++a2
	def zero=Nil
}

//ex:10.1 用Monoid实现 + , * , || , &
val intAddition: Monoid[Int] = new Monoid[Int] {def op(x: Int, y: Int) = x + y; val zero = 0}
val intMultiplication: Monoid[Int] = new Monoid[Int] {def op(x: Int, y: Int) = x * y; val zero = 1}
val booleanOr: Monoid[Boolean] = new Monoid[Boolean] {def op(x: Boolean, y: Boolean) = x || y; val zero = false}
val booleanAnd: Monoid[Boolean] = new Monoid[Boolean] {def op(x: Boolean, y: Boolean) = x && y; val zero = true}

//ex:10.2 实现option
def optionMonoid[A]: Monoid[Option[A]] = new Monoid[Option[A]] {
	def op(x: Option[A], y: Option[A]) = x orElse y
	val zero = None
}
// We can get the dual of any monoid just by flipping the `op`.
def dual[A](m: Monoid[A]): Monoid[A] = new Monoid[A] {def op(x: A, y: A): A = m.op(y, x); val zero = m.zero}
// Now we can have both monoids on hand:
def firstOptionMonoid[A]: Monoid[Option[A]] = optionMonoid[A]
def lastOptionMonoid[A]: Monoid[Option[A]] = dual(firstOptionMonoid)

//ex:10.3 编写一个自函数endoMonoid
//自函数:参数和返回值是相同类型的函数
def compose[A,B,C](f:B=>C,g:A=>B):A=>C = a => f(g(a))
def endoMonoid[A]: Monoid[A => A] = new Monoid[A => A] {
	def op(f: A => A, g: A => A) = f compose g
	val zero = (a: A) => a
}

//ex:10.4 
import fpinscala.testing._
import Prop._
def monoidLaws[A](m: Monoid[A], gen: Gen[A]): Prop =
// Associativity
	forAll(for {
		x <- gen
		y <- gen
		z <- gen
		} yield (x, y, z))(p =>
			m.op(p._1, m.op(p._2, p._3)) == m.op(m.op(p._1, p._2), p._3)) &&
// Identity
			forAll(gen)((a: A) =>m.op(a, m.zero) == a && m.op(m.zero, a) == a)


//10.2 使用monoid折叠列表
def foldRight[B](z:B)(f(A,B) => B):B
def foldLeft[B](z:B)(f(B,A) => B):B
//if the same 
def foldRight[B](z:A)(f(A,A) => A):A
def foldLeft[B](z:A)(f(A,A) => A):A

val words = List("north","west","east","south")
scala> val s = words.foldLeft(stringMonoid.zero)(stringMonoid.op)		--->s: String = northwesteastsouth
scala> val s = words.foldRight(stringMonoid.zero)(stringMonoid.op)		--->s: String = northwesteastsouth

words.foldLeft("")(_ + _) == (((("" +"north")+"west")+"east")+"south")
words.foldLeft("")(_ + _) == ("north"+("west"+("east"+("south"+""))))

//用Monoid折叠列表,编写一个通用的concatenate
def concatenate[A](as:List[A],m:Monoid[A]):A=as.foldLeft(m.zero)(m.op)

//ex:10.5 实现foldMap
def foldMap[A,B](as:List[A],m:Monoid[B])(f:A=>B):B = as.foldLeft(m.zero)((b, a) => m.op(b, f(a)))
//ex:10.6 用foldMap实现foldLeft和foldRight
def foldRight[A,B](as:List[A])(z:B)(f:(A,B) => B):B = foldMap(as,endoMonoid[B])(f.curried)(z)
def foldLeft[A, B](as:List[A])(z:B)(f:(B,A) => B):B = foldMap(as,dual(endoMonoid[B]))(a => b => f(b,a))(z)

//10.3 结合率和并行化
op(a,op(b,op(c,d)))
op(op(op(a,b),c),d)
op(op(a,b),op())

val words = List("north","west","east","south")
scala> List("north","west","east","south").foldLeft("")(_ + _)			--->res9: String = northwesteastsouth
//求值轨迹 左折叠
List("north","west","east","south").foldLeft("")(_ + _)
List("west","east","south").foldLeft("north")(_ + _)
List("east","south").foldLeft("northwest")(_ + _)
List("south").foldLeft("northwesteast")(_ + _)
List().foldLeft("northwesteastsouth")(_ + _)
---> "northwesteastsouth"

//ex:10.7 实现foldMapV
def foldMapV[A, B](as: IndexedSeq[A], m: Monoid[B])(f:A => B): B =
	if (as.length == 0) m.zero
	else if (as.length == 1) f(as(0))
	else {
		val (l,r) = as.splitAt(as.length / 2)
		m.op(foldMapV(l,m)(f),foldMapV(r,m)(f))
	}

//ex:10.8 实现组合子Par -> parFoldMap
def par[A](m: Monoid[A]): Monoid[Par[A]] = new Monoid[Par[A]] {
	def zero = Par.unit(m.zero)  
	def op(a: Par[A], b: Par[A]) = a.map2(b)(m.op)
}

// we perform the mapping and the reducing both in parallel
def parFoldMap[A,B](v:IndexedSeq[A],m:Monoid[B])(f: A => B): Par[B] = 
	Par.parMap(v)(f).flatMap { bs => foldMapV(bs, par(m))(b => Par.async(b)) }

//ex:10.9 用foldMap判断给定的IndexedSeq[Int]是否有序
def ordered(ints:IndexedSeq[Int]): Boolean = {
	val mon = new Monoid[Option[(Int,Int,Boolean)]] {
		def op(o1: Option[(Int,Int,Boolean)],o2: Option[(Int,Int,Boolean)]) =
			(o1,o2) match {
				case (Some((x1,y1,p)),Some((x2,y2,q))) => Some((x1 min x2, y1 max y2, p && q && y1 <= x2))
				case (x,None) => x
				case (None,x) => x
			}
		val zero = None
	}
	foldMapV(ints,mon)(i => Some((i,i,true))).map(_._3).getOrElse(true)
}

//10.4 例子:并行解析 P147 
//计算字符串里的单词个数
//ex:10.10 实现WCmonoid
sealed trait WC
case class Stub(chars: String) extends WC
case class Part(lStub: String, words: Int, rStub: String) extends WC
val wcMonoid: Monoid[WC] = new Monoid[WC] {
	val zero = Stub("")
	def op(a: WC, b: WC) = (a, b) match {
		case (Stub(c), Stub(d)) => Stub(c + d)
		case (Stub(c), Part(l, w, r)) => Part(c + l, w, r)
		case (Part(l, w, r), Stub(c)) => Part(l, w, r + c)
		case (Part(l1, w1, r1), Part(l2, w2, r2)) => Part(l1, w1 + (if ((r1 + l2).isEmpty) 0 else 1) + w2, r2)
	}
}

//ex:11.11 用wcMonoid实现 f: 用来递归拆分String并计算各自包含的单词个数
def count(s: String): Int = {
	def wc(c: Char): WC =if (c.isWhitespace) Part("", 0, "") else Stub(c.toString)
	def unstub(s: String) = s.length min 1
		foldMapV(s.toIndexedSeq, wcMonoid)(wc) match {
			case Stub(s) => unstub(s)
			case Part(l, w, r) => unstub(l) + w + unstub(r)
		}
}

//monoid同态
"foo".length+"bar".length == ("foo"+"bar").length
//一个monoid同态f定义为在monoid M和N之间对所有的值及x和y都遵守
M.op(f(x),f(y)) == f(N.op(x,y))

//10.5 可折叠数据结构
//构造一个高阶类型构造函数
trait Foldable[F[_]]{						//F[_] 类型构造器
	def foldRight[A,B](as:F[A])(z:B)(f:(A,B)=>B):B
	def foldLeft[A,B](as:F[A])(z:B)(f:(B,A)=>B):B
	def foldMap[A,B](as:F[A])(f:A=>B)(mb:Monoid[B]):B
	def concatenate[A](as:F[A])(m:Monoid[A]):A = foldLeft(as)(m.zero)(m.op)
}

//ex:10.12 实现Foldable,ListFoldable,IndexedSeqFoldable,StreamFoldable
trait Foldable[F[_]] {
	def foldRight[A, B](as: F[A])(z: B)(f: (A, B) => B): B = foldMap(as)(f.curried)(endoMonoid[B])(z)
	def foldLeft[A, B](as: F[A])(z: B)(f: (B, A) => B): B = foldMap(as)(a => (b: B) => f(b, a))(dual(endoMonoid[B]))(z)
	def foldMap[A, B](as: F[A])(f: A => B)(mb: Monoid[B]): B =foldRight(as)(mb.zero)((a, b) => mb.op(f(a), b))
	def concatenate[A](as: F[A])(m: Monoid[A]): A = foldLeft(as)(m.zero)(m.op)
}
object ListFoldable extends Foldable[List] {
	override def foldRight[A, B](as: List[A])(z: B)(f: (A, B) => B) = as.foldRight(z)(f)
	override def foldLeft[A, B](as: List[A])(z: B)(f: (B, A) => B) = as.foldLeft(z)(f)
	override def foldMap[A, B](as: List[A])(f: A => B)(mb: Monoid[B]): B = foldLeft(as)(mb.zero)((b, a) => mb.op(b, f(a)))
}
object IndexedSeqFoldable extends Foldable[IndexedSeq] {
	import Monoid._
	override def foldRight[A, B](as: IndexedSeq[A])(z: B)(f: (A, B) => B) = as.foldRight(z)(f)
	override def foldLeft[A, B](as: IndexedSeq[A])(z: B)(f: (B, A) => B) = as.foldLeft(z)(f)
	override def foldMap[A, B](as: IndexedSeq[A])(f: A => B)(mb: Monoid[B]): B = foldMapV(as, mb)(f)
}
object StreamFoldable extends Foldable[Stream] {
	override def foldRight[A, B](as: Stream[A])(z: B)(f: (A, B) => B) = as.foldRight(z)(f)
	override def foldLeft[A, B](as: Stream[A])(z: B)(f: (B, A) => B) = as.foldLeft(z)(f)
}

//ex:10.13 实现TreeFoldable的实例
sealed trait Tree[+A]
case class Leaf[A](value: A) extends Tree[A]
case class Branch[A](left: Tree[A], right: Tree[A]) extends Tree[A]

object TreeFoldable extends Foldable[Tree] {
	override def foldMap[A, B](as: Tree[A])(f: A => B)(mb: Monoid[B]): B = as match {
		case Leaf(a) => f(a)
		case Branch(l, r) => mb.op(foldMap(l)(f)(mb), foldMap(r)(f)(mb))
	}
	override def foldLeft[A, B](as: Tree[A])(z: B)(f: (B, A) => B) = as match {
		case Leaf(a) => f(z, a)
		case Branch(l, r) => foldLeft(r)(foldLeft(l)(z)(f))(f)
	}
	override def foldRight[A, B](as: Tree[A])(z: B)(f: (A, B) => B) = as match {
		case Leaf(a) => f(a, z)
		case Branch(l, r) => foldRight(l)(foldRight(r)(z)(f))(f)
	}
}

//ex:10.14 实现OptionFoldable
object OptionFoldable extends Foldable[Option] {
	override def foldMap[A, B](as: Option[A])(f: A => B)(mb: Monoid[B]): B =
	as match {case None => mb.zero ; case Some(a) => f(a)}
	override def foldLeft[A, B](as: Option[A])(z: B)(f: (B, A) => B) = as match {case None => z ; case Some(a) => f(z, a)}
	override def foldRight[A, B](as: Option[A])(z: B)(f: (A, B) => B) = as match {case None => z ; case Some(a) => f(a, z)}
}

//ex:10.15 使用Foldable结构转化List
def toList[A](as: F[A]): List[A] = foldRight(as)(List[A]())(_ :: _)


//10.6 组合monoid

//ex:10.17 编写monoid实例
def productMonoid[A,B](A: Monoid[A], B: Monoid[B]): Monoid[(A, B)] =
	new Monoid[(A, B)] {
		def op(x: (A, B), y: (A, B)) = (A.op(x._1, y._1), B.op(x._2, y._2))
		val zero = (A.zero, B.zero)
	}

//10.6.1 组装更加复杂的monoid
//示例10.1 合并key-value Map
def mapMergeMonoid[K,V](V:Monoid[V]):Monoid[Map[K,V]] = 
	new Monoid[Map[K,V]]{
		def zero = Map[K,V]()
		def op(a:Map[K,V],b:Map[K,V])=(a.keySet++b.keySet).foldLeft(zero){
			(acc,k)=>acc.updated(k,V.op(a.getOrElse(k,V.zero),b.getOrElse(k,V.zero)))
		}
}
//使用mapMergeMonoid组合子,构建复杂monoid
val M:Monoid[Map[String,Map[String,Int]]] = mapMergeMonoid(mapMergeMonoid(intAddition))
val m1 = Map("o1"->Map("a"->1,"b"->2))
val m2 = Map("o1"->Map("c"->3))
scala> val m3 = M.op(m1,m2)				--->m3: Map[String,Map[String,Int]] = Map(o1 -> Map(a -> 1, b -> 2, c -> 3))

//ex:10.17 编写monoid实例
def functionMonoid[A,B](B: Monoid[B]): Monoid[A => B] =
	new Monoid[A => B] {
		def op(f: A => B, g: A => B) = a => B.op(f(a),g(a))
		val zero: A => B = a => B.zero
	}

//ex:10.18 实现bag函数
def mapMergeMonoid[K,V](V: Monoid[V]): Monoid[Map[K, V]] =
	new Monoid[Map[K, V]] {
		def zero = Map[K,V]()
		def op(a: Map[K,V], b: Map[K,V]) =
			(a.keySet ++ b.keySet).foldLeft(zero) {(acc,k) =>acc.updated(k,V.op(a.getOrElse(k,V.zero),b.getOrElse(k,V.zero)))}
	}

def bag[A](as: IndexedSeq[A]): Map[A, Int] = foldMapV(as, mapMergeMonoid[A, Int](intAddition))((a: A) => Map(a -> 1))

//10.6.2 使用组合的monoid融合多个遍历
val m = productMonoid(intAddition,intAddition)
val p = listFoldable.foldMap(List(1,2,3,4))(a=>(1,a))(m)
val mean = p._1/p._2.toDouble


=========================================================CP11 Monad
//函子:	http://hongjiang.info/understand-monad-4-what-is-functor/	
//11.1函子:对map函数的泛化
def map[A,B](ga:Gen[A])(f:A=>B):Gen[B]
def map[A,B](ga:Parser[A])(f:A=>B):Parser[B]
def map[A,B](ga:Option[A])(f:A=>B):Option[B]
---> //使用构造器F[_]参数化map
import scala.language.higherKinds
trait Functor[F[_]]{def map[A,B](fa:F[A])(f:A=>B):F[B]}

val listFunctor=new Functor[List]{def map[A,B](as:List[A])(f:A=>B):List[B]= as map f}
listFunctor.map(List(1,2,3))((x:Int)=>x.toString)	//ex

//+distribute (kind like unzip)
trait Functor[F[_]]{
	def map[A,B](fa:F[A])(f:A=>B):F[B]
	def distribute[A,B](fab:F[(A,B)]):(F[A],F[B])=(map(fab)(_._1),map(fab)(_._2))
}

def codistribute[A,B](e:Either[F[A],F[B]]):F[Either[A,B]]=e match {
	case Left(fa)=>map(fa)(Left(_))
	case Right(fb)=>map(fb)(Right(_))
}

//11.1.1 函子法则
//保持结构不变,不抛出异常,移除list头元素,将Some转化为None ...
def distribute[A,B](fab:F[(A,B)]):(F[A],F[B])
def codistribute[A,B](e:Either[F[A],F[B]]):F[Either[A,B]]

//11.2 Monad:对flapMap和unit函数的泛化
//ex11.1 为Gen,Parser和Option实现map2
def map2[A,B,C](fa:Gen[A],fb:Gen[B])(f:(A,B)=>C):Gen[C]= fa flatMap(a=>fb map (b=>f(a,b)))
def map2[A,B,C](fa:Parser[A],fb:Parser[B])(f:(A,B)=>C):Parser[C]= fa flatMap(a=>fb map (b=>f(a,b)))
def map2[A,B,C](fa:Option[A],fb:Option[B])(f:(A,B)=>C):Option[C]= fa flatMap(a=>fb map (b=>f(a,b)))

//Monad 特质
//示例11.2 为map2创建一个Mon trait
trait Mon[F[_]]{def map2[A,B,C](fa:F[A],fb:F[B])(f:(A,B)=>C):F[C]= fa flatMap(a=>fb map (b=>f(a,b)))}   //因为在上下文中未定义map和flatmap
//示例11.3 添加map和flatMap
trait Mon[F[_]]{
	def map[A,B](fa:F[A])(f:A=>B):F[B]
	def flatMap[A,B](fa:F[A])(f:A=>F[B]):F[B]
	def map2[A,B,C](fa:F[A],fb:F[B])(f:(A,B)=>C):F[C]= flatMap(fa)(a=>map(fb)(b=>f(a,b)))
}

//11.4 创建Monad trait
trait Monad[F[_]] extends Functor[F]{
	def unit[A](a: =>A):F[A]
	def flatMap[A,B](ma:F[A])(f:A=>F[B]):F[B]
	def map[A,B](ma:F[A])(f: A=>B):F[B]=flatMap(ma)(a=>unit(f(a)))
	def map2[A,B,C](ma:F[A],mb:F[B])(f:(A,B)=>C):F[C]=flatMap(ma)(a=>map(mb)(b=>f(a,b)))
}

//11.5 对Gen实现 Monad
object Monad{
	val genMonad=new Monad[Gen]{
		def unit[A](a: =>A):Gen[A]=Gen.unit(a)
		def flatMap[A,B](ma:Gen[A])(f:A=>Gen[B]):Gen[B]=ma flatMap f
		}
}

//ex:11.11 用monad实现par,parser,option,stream,list
val parMonad = new Monad[Par] {
	def unit[A](a: => A) = Par.unit(a)
	def flatMap[A,B](ma: Par[A])(f: A => Par[B]) = Par.flatMap(ma)(f)
}

def parserMonad[P[+_]](p: Parsers[P]) = new Monad[P] {
	def unit[A](a: => A) = p.succeed(a)
	def flatMap[A,B](ma: P[A])(f: A => P[B]) = p.flatMap(ma)(f)
}

val optionMonad = new Monad[Option] {
	def unit[A](a: => A) = Some(a)
	def flatMap[A,B](ma: Option[A])(f: A => Option[B]) = ma flatMap f
}

val streamMonad = new Monad[Stream] {
	def unit[A](a: => A) = Stream(a)
	def flatMap[A,B](ma: Stream[A])(f: A => Stream[B]) = ma flatMap f
}

val listMonad = new Monad[List] {
	def unit[A](a: => A) = List(a)
	def flatMap[A,B](ma: List[A])(f: A => List[B]) = ma flatMap f
}

//ex:11.2 
class StateMonads[S] {
	type StateS[A] = State[S, A]
	val monad = new Monad[StateS] {
		def unit[A](a: => A): State[S, A] = State(s => (a, s))
		override def flatMap[A,B](st: State[S, A])(f: A => State[S, B]): State[S, B] = st flatMap f
	}
}

def stateMonad[S] = new Monad[({type f[x] = State[S, x]})#f] {
	def unit[A](a: => A): State[S, A] = State(s => (a, s))
	override def flatMap[A,B](st: State[S, A])(f: A => State[S, B]): State[S, B] = st flatMap f
}

//11.3 Monadic组合子
//ex:11.3 monad 实习那sequence和traverse
def sequence[A](lma: List[F[A]]): F[List[A]] = lma.foldRight(unit(List[A]()))((ma, mla) => map2(ma, mla)(_ :: _))
def traverse[A,B](la: List[A])(f: A => F[B]): F[List[B]] = la.foldRight(unit(List[B]()))((a, mlb) => map2(f(a), mlb)(_ :: _))
def bsequence[A](ms: Seq[F[A]]): F[IndexedSeq[A]] = {
	if (ms.isEmpty) point(Vector())
	else if (ms.size == 1) ms.head.map(Vector(_))
  	else {
		val (l,r) = ms.toIndexedSeq.splitAt(ms.length / 2)
		map2(bsequence(l), bsequence(r))(_ ++ _)
	}
}

//ex:11.4 实现replicateM
def _replicateM[A](n: Int, ma: F[A]): F[List[A]] = if (n <= 0) unit(List[A]()) else map2(ma, replicateM(n - 1, ma))(_ :: _)
def replicateM[A](n: Int, ma: F[A]): F[List[A]] = sequence(List.fill(n)(ma))

def product[A,B](ma:F[A],mb:F[B]):F[(A,B)]=map2(ma,mb)(_,_)

//ex:11.6 实现
def filterM[A](ms: List[A])(f: A => F[Boolean]): F[List[A]] =
	ms match {
		case Nil => unit(Nil)
		case h :: t => flatMap(f(h))(b =>if (!b) filterM(t)(f) else map(filterM(t)(f))(h :: _))
	}


//11.4 单子定律P158
//11.4.1结合法则
//示例11.6 定义Order class 
case class Order(item:Item,quantity:Int)
case class Item(name:String,price:Double)

val genOrder:Gen[Order]= for {name<-Gen.stringN(3);price<-Gen.uniform.map(_*10);quantity<-Gen.choose(1,100)} yield Order(Item(name,price),quantity)
val genItem:Gen[Item]=for{name<-Gen.stringN(3);price<-Gen.uniform.map(_*10)} yield Item(name,price)
//or 2
val genOrder:Gen[Order]=for{item<-genItem;quantity<-Gen.choose(1,100)} yield Order(item,quantity)
//默认flatMap遵循结合法则
x.flatMap(f).flatMap(g) == x.flatMap(a=>f(a).flatMap(g))

//11.4.2 为指定monad证明结合法则
//首先证明对option成立
None.flatMap(f).flatMap(g) == None.flatMap(a=>f(a).flatMap(g))
	--> None == None
x.flatMap(f).flatMap(g) == x.flatMap(a=>f(a).flatMap(g))		//原始法则
Some(v).flatMap(f).flatMap(g) == Some(v).flatMap(a=>f(a).flatMap(g))	
	f(v).flatMap(g) == (a=>f(a).flatMap(g))(v)
	f(v).flatMap(g) == f(v).flatMap(g)

//KLEISLI组合:结合律更清晰的视图
op(op(x,y),z) == op(x,op(y,z))
def compose[A,B,C](f: A=>F[B],g: B=>F[C]): A => F[C]

//ex:11.7 实现kleisli composition函数 compose
def compose[A,B,C](f: A=>F[B],g: B=>F[C]): A => F[C] = a => flatMap(f(a))(g)
	compose(compose(f,g),h) == compose(f,compose(g,h))
//ex:11.8 使用conpose实现flatMap
def flatMap[A,B](ma: F[A])(f: A=>F[B]):F[B] = compose((_:Unit) => ma, f)(())

//ex:11.9 展示使用flatMap和compose构建associative法则是相同的
//Let's rewrite the following in terms of `flatMap`:
compose(compose(f, g), h) == compose(f, compose(g, h))
a => flatMap(compose(f, g)(a))(h) == a => flatMap(f(a))(compose(g, h))
a => flatMap((b => flatMap(f(b))(g))(a))(h) == a => flatMap(f(a))(b => flatMap(g(b))(h))

//So far we have just expanded the definition of `compose`. Equals substituted for equals.
//Let's simplify the left side a little:
a => flatMap(flatMap(f(a))(g))(h) == a => flatMap(f(a))(b => flatMap(g(b))(h))

//Let's simplify again by eliminating the `a` argument and substituting a hypothetical value `x` for `f(a)`:
flatMap(flatMap(x)(g))(h) == flatMap(x)(b => flatMap(g(b))(h))
//This now looks exactly like the monad law stated in terms of `flatMap`, just with different names:
flatMap(flatMap(x)(f))(g) == flatMap(x)(a => flatMap(f(a))(g))


//11.4.3 单位元法则
//单位元元素:
def unit[A](a: =>A):F[A]
//左identity == 右identity
compose(f,unit) == f
compose(unit,f) == f

flatMap(x)(unit) == x
flatMap(unit(y))(f) == f(y)

//ex:11.10 说明identity法则的两个声明是相同的
// We simply substitute the definition of `compose` in terms of `flatMap`.
compose(f, unit)(v) == f(v)   		         // for all functions f and values v
(a => flatMap(f(a))(unit))(v) == f(v) 		 // Expand `compose`
flatMap(f(v))(unit) == f(v)          		 // Simplify function application
flatMap(x)(unit) == x		                 // Abstract out `f(v)`

compose(unit, f)(x) == f(x)
flatMap(unit(x))(f) == f(x)		 	 // Expand `compose`

//ex:11.11 证明你所选择的monad实例遵从identity法则
For `Option`, we again consider both cases `None` and `Some` and expand the equation.
The monadic `unit` is the `Some(_)` constructor.

flatMap(None)(Some(_)) == None			// Left identity is trivially true for None:
flatMap(Some(v))(Some(_)) == Some(v)		// And here it is for Some:
Some(v) == Some(v)				// Substitute the definition of `flatMap`:
flatMap(Some(None))(f) == f(None)		// Right identity is just as easy for None:
f(None) == f(None)				// Substitute definition of flatMap:
flatMap(Some(Some(v)))(f) == f(Some(v))		// And for Some:
f(Some(v)) == f(Some(v))			// Substitute definition of flatMap:

//ex:11.12 使用flatMap实现join
def join[A](mma: F[F[A]]): F[A] = flatMap(mma)(ma => ma)

//ex:11.13 使用join和map 实现flatMap或compose
def flatMap[A,B](ma: F[A])(f: A => F[B]) = join(map(ma)(f))
def compose[A,B,C](f: A => F[B], g: B => F[C]): A => F[C] = a => join(map(f(a))(g))

//ex:11.14 使用join,map和unit重新陈述monad

//ex:11.15 解释对par和parser来说associative意味着什么
We can look at the associative law in terms of `flatMap` from another perspective. 
It says that `x.flatMap(f).flatMap(g)` is equal to `x.flatMap(a => f(a).flatMap(g))` _for all_ choices of `f` and `g`. 
So let's pick a particular `f` and `g` that's easy to think about. We can just pick the identity function:

x.flatMap(z => z).flatMap(z => z) == x.flatMap(a => a.flatMap(z => z))

And of course, flatMapping with the identify function is `join`! The associative law can now be stated as:

join(join(x)) == x.flatMap(join)

And we know that `flatMap` is "map, then join," so let's eliminate this last call to `flatMap`:

join(join(x)) == join(map(x)(join))

The identity laws in terms of `join` are:

join(map(x)(unit)) == x
join(unit(x)) == x

This follows from the definition of `join` and the identity laws in terms of `flatMap`:

flatMap(x)(unit) == x
flatMap(unit(x))(f) == f(x)

For the second law, we simply substitute the identity function for `f`, which gives us `join`.

Let's make a fast-and-loose proof for this version of the associative law using the `List` monad as an example. 
Of course, `join` in the `List` monad is just _list concatenation_:

scala> listMonad.join(List(List(1, 2), List(3, 4)))			--->res0: List[Int] = List(1, 2, 3, 4)

Now let's say we have some lists, nested to a depth of three:

val ns: List[List[List[Int]]] =List(List(List(1,2), List(3,4)),List(List(), List(5)))

If we `join` this list, the outer lists get concatenated and we have a list of lists two levels deep:

scala> ns.flatten				--->res1: List[List[Int]] = List(List(1, 2), List(3, 4), List(), List(5))

If we instead _map_ `join` over it, we get a different nesting but again two levels deep. This flattens the _inner_ lists.

scala> ns.map(listMonad.join)			--->res2: List[List[Int]] = List(List(1, 2, 3, 4), List(5))

And then joining `res1` should be the same as joining `res2`:

scala> listMonad.join(res1) == listMonad.join(res2)			--->res3: Boolean = true

So all that the associative law is saying for the `List` monad is that concatenating the outer lists and then the inner ones (`join(join(ns))`) is the same as first concatenating the inner lists and then the outer ones (`join(ns.map(join))`).

//ex:11.16 对于Gen和List来说identity法则意味着什么
Recall the identity laws:

left identity:  flatMap(unit(x))(f) == f(x)
right identity: flatMap(x)(unit)    == x

The left identity law for `Gen`:
The law states that if you take the values generated by `unit(x)` (which are always `x`) and apply `f` to those values, that's exactly the same as the generator returned by `f(x)`.

The right identity law for `Gen`:
The law states that if you apply `unit` to the values inside the generator `x`, that does not in any way differ from `x` itself.

The left identity law for `List`:
The law says that wrapping a list in a singleton `List` and then flattening the result is the same as doing nothing.

The right identity law for `List`:
The law says that if you take every value in a list, wrap each one in a singleton `List`, and then flatten the result, you get the list you started with.


//11.5 什么是Monad
//11.5.1 identity monad
case class Id[A](value:A)
//ex:11.17 实现Monad[id]
case class Id[A](value: A) {
	def map[B](f: A => B): Id[B] = Id(f(value))
	def flatMap[B](f: A => Id[B]): Id[B] = f(value)
}

object Id2 {
	val idMonad = new Monad[Id] {
		def unit[A](a: => A) = Id(a)
		def flatMap[A,B](ida: Id[A])(f: A => Id[B]): Id[B] = ida flatMap f
	}
}

scala> Id("Hello, ") flatMap (a=>Id("monad!") flatMap (b=>Id(a+b)))			--->res50: Id[String] = Id(Hello, monad!)

//11.5.2 状态monad和partial type application
//ex: 回顾状态与数据类型 p163
case class State[S,A](run:S=>(A,S)){
	def map[B](f:A=>B):State[S,B]=State(s=>{val (a,s1)=run(s); (f(a),s1)})
	def flatMap[B](f:A=>State[S,B]):State[S,B]=State(s=>{val (a,s1)=run(s); f(a).run(s1)})
}

type IntState[A]=State[Int,A]
object IntStateMonad extends Monad[IntState]{
	def unit[A](a: =>A):IntState[A]=State(s=>(a,s))
	def flatMap[A,B](st:IntState[A])(f: A=>IntState[B]):IntState[B]=st flatMap f
}

//类型lambda
def stateMonad[S]=new Monad[({type f[x]=State[S,x]}) #f]{
	def unit[A](a: =>A):State[S,A]=State(s=>(a,s))
	def flatMap[A,B](st:State[S,A])(f:A=>State[S,B]):State[S,B]=st flatMap f}



//ex:11.19 getState,setState,unit,flatMap共同保持了什么法则
// Getting and setting the same state does nothing:
getState.flatMap(setState) == unit(())
// written as for-comprehension:
for {x <- getState; _ <- setState(x)} yield ()
// Setting the state to `s` and getting it back out yields `s`.
setState(s).flatMap(_ => getState) == unit(s)
// alternatively:
for {_ <- setState(s); x <- getState} yield x


//示例11.8 在for推导中获取和设置状态
val F = stateMonad[Int]
def zipWithIndex[A](as:List[A]):List[(Int,A)] = as foldLeft(F.unit(List[(Int,A)]()))
	((acc,a) => for{xs<-acc;n<-getState; _ <-setState(n+1)} yield (n,a)::xs).run(0)._.reverse


//ex:11.20
object Reader {
	def readerMonad[R] = new Monad[({type f[x] = Reader[R,x]})#f] {
		def unit[A](a: => A): Reader[R,A] = Reader(_ => a)
		def flatMap[A,B](st: Reader[R,A])(f: A => Reader[R,B]): Reader[R,B] = Reader(r => f(st.run(r)).run(r))
}
// A primitive operation for it would be simply to ask for the `R` argument:
	def ask[R]: Reader[R, R] = Reader(r => r)
}


=========================================================CP12 可应用和可遍历函子
//12.1 泛化单子
def sequence[A](lfa:List[F[A]]):F[List[A]] 
	traverse(lfa)(fa=>fa)
def traverse[A,B](as:List[A])(f:A=>F[B]):F[List[B]] 
	as.foldRight(unit(List[B]()))((a,mbs)=>map2(f(a),mbs)(_ :: _))
def map2[A,B,C](ma:F[A],mb:F[B])(f:(A,B)=>C):F[C] = flatMap(ma)(a=>map(mb)(b=>f(a,b)))

//12.2 Applicative trait
//示例12.1 创建Applicative 接口
trait Applicative[F[_]] extends Functor[F]{
	def map2[A,B,C](fa:F[A],fb:F[B])(f:(A,B)=>C): F[C]
	def unit[A](a: =>A): F[A]
	def map[B](fa:F[A])(f:A=>B):F[B]=map2(fa,unit(()))((a,_)=>f(a))
	def traverse[A,B](as:List[A])(f: A=>F[B]):F[List[B]]
		as.foldRight(unit(List[B]()))((a,fbs)=>map2(f(a),fbs)(_ :: _))
}

//
trait Applicative[F[_]] extends Functor[F] {
	def map2[A,B,C](fa: F[A], fb: F[B])(f: (A, B) => C): F[C] = apply(map(fa)(f.curried))(fb)
	def apply[A,B](fab: F[A => B])(fa: F[A]): F[B] = map2(fab, fa)(_(_))
	def unit[A](a: => A): F[A]
	def map[A,B](fa: F[A])(f: A => B): F[B] = apply(unit(f))(fa)
	def sequence[A](fas: List[F[A]]): F[List[A]] = traverse(fas)(fa => fa)
	def traverse[A,B](as: List[A])(f: A => F[B]): F[List[B]] = as.foldRight(unit(List[B]()))((a, fbs) => map2(f(a), fbs)(_ :: _))
	def replicateM[A](n: Int, fa: F[A]): F[List[A]] = sequence(List.fill(n)(fa))
	def factor[A,B](fa: F[A], fb: F[B]): F[(A,B)] = map2(fa, fb)((_,_))
	def product[G[_]](G: Applicative[G]): Applicative[({type f[x] = (F[x], G[x])})#f] = {
		val self = this
		new Applicative[({type f[x] = (F[x], G[x])})#f] {
			def unit[A](a: => A) = (self.unit(a), G.unit(a))
			override def apply[A,B](fs: (F[A => B], G[A => B]))(p: (F[A], G[A])) = (self.apply(fs._1)(p._1), G.apply(fs._2)(p._2))
		}
}
}

//ex:12.1 尽可能将Monad组合子移动到Applicative组合子,只使用map2和unit
def sequence[A](fas: List[F[A]]): F[List[A]] = traverse(fas)(fa => fa)
def replicateM[A](n: Int, fa: F[A]): F[List[A]] = sequence(List.fill(n)(fa))
def product[A,B](fa: F[A], fb: F[B]): F[(A,B)] =map2(fa, fb)((_,_))

//ex:12.2 实现applicative接口
trait Applicative[F[_]] extends Functor[F] {
	def map2[A,B,C](fa: F[A], fb: F[B])(f: (A, B) => C): F[C] = apply(map(fa)(f.curried), fb)
	def apply[A,B](fab: F[A => B])(fa: F[A]): F[B] = map2(fab, fa)(_(_))
	def unit[A](a: => A): F[A]
	def map[A,B](fa: F[A])(f: A => B): F[B] = apply(unit(f))(fa)
}

//ex:12.3 实现map3和map4
def map3[A,B,C,D](fa: F[A], fb: F[B], fc: F[C])(f: (A, B, C) => D): F[D] = apply(apply(apply(unit(f.curried))(fa))(fb))(fc)
def map4[A,B,C,D,E](fa: F[A], fb: F[B], fc: F[C], fd: F[D])(f: (A, B, C, D) => E): F[E] =apply(apply(apply(apply(unit(f.curried))(fa))(fb))(fc))(fd)

//ex12.2 让Monad成为Applicative的子类型
trait Monad[F[_]] extends Applicative[F]{
	def flatMap[A,B](fa:F[A])(f:A=>F[B]):F[B] = join(map(fa)(f))
	def join[A](ffa:F[F[A]]):F[A]=flatMap(ffa)(fa=>fa)
	def compose[A,B,C](f:A=>F[B],g:B=>F[C]):A=>F[C] = a=>flatMap(f(a))(g)
	def map[A,B](fa:F[A])(f:A=>B):F[B]=flatMap(fa)((a:A) => unit(f(a)))
	def map2[A,B,C](fa:F[A],fb:F[B])(f:(A,B)=>C):F[C] = flatMap(fa)(a=>map(fb)(b=>f(a,b)))
}


//12.3 单子与可应用函子的区别
//12.3.1 对比Option applicative 与 Option monad
//示例12.3 使用Option applicative组合结果
val F:Applicative[Option] = ...
val dept:Map[String,String] = ...
val salaries:Map[String,Double] = ...
val o: Option[String]=F.map2(depts.get("Alice"),salaries.get("Alice"))((dept,salary)=>s"Alice in $dept makes $salary per year")

//示例12.4 使用Option monad组合结果
val idByName:Map[String,Int]
val depts:Map[String,String] = ...
val salaries:Map[String,Double] = ...
val o:Option[String] = idByName.get("Bob").flatMap{id => F.map2(depts.get(id),salaries.get(id))(dept,salary)=>s"Bob in $dept makes $salary per year "}

//12.3.2 对比Parser_applicative 与 Parser_monad
case class Row(date:Date,temperature:Double)
val F:Applicative[Parser] = ...
val d:Parser[Date] = ...
val temp:Parser[Double] = ...
val row:Parser[Row]=F.map2(d.temp)(Row(_,_))
val rows: Parser[List[Row]] = row.sep("\n")


case class Row(date:Date,temperature:Double)
val F:Monad[Parser] = ...
val d:Parser[Date] = ...
val temp:Parser[Double] = ...
val header:Parser[Parser[Row]] = ...
val rows:Parser[List[Row]] = F.flatMap(header){row=>row.seq("\n")}


//12.4 可应用函子的优势
//12.4.1 不是所有的可应用函子都是Monad
//可应用Stream
val streamApplicative = new Applicative[Stream]{
	def unit[A](a: =>A):Stream[A] = Stream.continually(a)
	def map2[A,B,C](a:Stream[A],b:Stream[B])(f:(A,B)=>C):Stream[C] = a zip b map f.tupled
}

//校验:用Either变量累计错误
//ex:12.5 为Either写一个monad实例
def eitherMonad[E]: Monad[({type f[x] = Either[E, x]})#f] =
	new Monad[({type f[x] = Either[E, x]})#f] {
		def unit[A](a: => A): Either[E, A] = Right(a)
		def flatMap[A,B](eea: Either[E, A])(f: A => Either[E, B]) = eea match {
			case Right(a) => f(a)
			case Left(e) => Left(e)
		}
	}

validName(field1) flatMap (f1 =>validBirthdate(field2) flatMap(f2=>validPhone(field3) map (f3=>WebForm(f1,f2,f3))))
map3:
map3(validName(field1),validBirthdate(field2),validPhone(field3))(WebForm(_,_,_))

//创建一个数据类型Validation
sealed trait Validation[+E,+A]
case class Failure[E](head:E,tail:Vector[E]=Vector()) extends Validation[E,Nothing]
case class Success[A](a:A) extends Validation[Nothing,A]

//ex:12.6 为Validation写一个Applicative实例
def validationApplicative[E]: Applicative[({type f[x] = Validation[E,x]})#f] =
	new Applicative[({type f[x] = Validation[E,x]})#f] {
		def unit[A](a: => A) = Success(a)
		override def map2[A,B,C](fa: Validation[E,A], fb: Validation[E,B])(f: (A, B) => C) =
			(fa, fb) match {
				case (Success(a), Success(b)) => Success(f(a, b))
				case (Failure(h1, t1), Failure(h2, t2)) => Failure(h1, t1 ++ Vector(h2) ++ t2)
				case (e@Failure(_, _), _) => e
				case (_, e@Failure(_, _)) => e
			}
	}

//示例12.5 校验用户在表单上的输入
def validName(name:String): Validation[String,String] = if (name != "") Success(name) else Failure("Name cannot be empty")
def validBirthdate(birthdate:String):Validation[String,Date] = 
	try{import java.text._ ; Success((new SimpleDateFormat("yyyy-MM-dd").parse(birthdate)}
	catch{Failure("Birthdate must be in the form yyyy-MM-dd")}
def validPhone(phoneNumber:String):Validation[String,String] = 
	if(phoneNumber.matches("[0-9]{10}")) Success(phoneNumber)
	else Failure("Phone number must be 10 digits")
def validWebForm(name:String,birthdate:String,phone:String):Validation[String,WebForm] = 
	map3(validName(name),validBirthdate(birthdate),validPhone(phone))(WebForm(_,_,_))


//12.5 可应用法则
//12.5.1 Left and right identity (左右相等性)
map(v)(id) == v
map(map(v)(g)(f)) == map(v)(f compose g)
def map[B](fa:F[A])(f:A=>B):F[B] = map2(fa,unit(()))((a,_)=>f(a))
def map[B](fa:F[A])(f:A=>B):F[B] = map2(unit(()),fa)((_,a)=>f(a))
//左右相等
map2(unit(()),fa)((_,a)=>a) == fa
map2(fa,unit(()))((a,_)=>a) == fa

//12.5.2 结合律
op(a,op(b,c)) == op(op(a,b),c)
compose(f,op(g,h)) == compose(compose(f,g),h)

def assoc[A,B,C](p:(A,(B,C))):((A,B),C) = p match {case (a,(b,c)) => ((a,b),c)}
def product[A,B](fa:F[A],fb:F[B]):F[(A,B)]=map(fa,fb)((_,_))

//12.5.3 Naturality of product
//示例12.6 提取员工姓名和年薪
val F:Applicative[Option] = ...
case class Employee(name:String,id:Int)
case class Pay(rate:Double,hoursPerYear:Double)
def format(e:Option[Employee],pay:Option[Pay]):Option[String] = F.map2(e,pay){(e,pay)=>s"${e.name} makes ${pay.rate*pay.hoursPerYear}"}
val e:Option[Employee] = ...
val pay:Option[Pay] = ...
format(e,pay)

//示例12.7 重构format
val F:Applicative[Option] = ...
def format(name:Option[String],pay:Option[Double]):Option[String]=F.map2(e,pay){s"$e makes $pay"}
val e = Option[Employee]
val pay :Option[Pay] = ...
format(F.map(e)(_.name),F.map(pay)(pay=>pay.rate*pay.hoursPerYear))
//
map2(a,b)(productF(f,g)) == product(map(a)(f),map(b)(g))
def productF[I,O,I2,O2](f:I=>O,g:I2=>O2):(I,I2)=>(O,O2) = (i,i2)=>(f(i),g(i2))

//ex:12.8 对2个monod进行product实现monoid[A,B]
def product[G[_]](G: Applicative[G]): Applicative[({type f[x] = (F[x], G[x])})#f] = {
	val self = this
	new Applicative[({type f[x] = (F[x], G[x])})#f] {
		def unit[A](a: => A) = (self.unit(a), G.unit(a))
		override def apply[A,B](fs: (F[A => B], G[A => B]))(p: (F[A], G[A])) = (self.apply(fs._1)(p._1), G.apply(fs._2)(p._2))
	}
}


//ex:12.9 实现compose
def compose[G[_]](G: Applicative[G]): Applicative[({type f[x] = F[G[x]]})#f] = {
	val self = this
	new Applicative[({type f[x] = F[G[x]]})#f] {
	def unit[A](a: => A) = self.unit(G.unit(a))
	override def map2[A,B,C](fga: F[G[A]], fgb: F[G[B]])(f: (A,B) => C) = self.map2(fga, fgb)(G.map2(_,_)(f))
	}
}

//ex:12.11 合成Monad
def flatMap[A,B](mna: F[G[A]])(f: A => F[G[B]]): F[G[B]] = self.flatMap(na => G.flatMap(na)(a => ???))

//12.6 可遍历函子
def traverse[F[_],A,B](as:List[A])(f:A=>F[B]):F[List[B]]
def sequence[F[_],A](fas:List[F[A]]):F[List[A]]

//ex:12.12  在Applicative trait中,对Map而非List实现sequence
def sequenceMap[K,V](ofa: Map[K,F[V]]): F[Map[K,V]] =
	(ofa foldLeft unit(Map.empty[K,V])) { case (acc, (k, fv)) =>map2(acc, fv)((m, v) => m + (k -> v))}


//实现Traverse
trait Traverse[F[_]]{
	def traverse[G[_]:Applicative,A,B](fa:F[A])(f:A=>G[B]):G[F[B]] = sequence(map(fa)(f))
	def sequence[G[_]:Applicative,A](fga:F[G[A]]):G[F[A]] = traverse(fga)(ga=>ga)
}

//ex:12.13 对List,Option和Tree实现Traverse实例
val listTraverse = new Traverse[List] {
	override def traverse[G[_],A,B](as: List[A])(f: A => G[B])(implicit G: Applicative[G]): G[List[B]] =
		as.foldRight(G.unit(List[B]()))((a, fbs) => G.map2(f(a), fbs)(_ :: _))
}

val optionTraverse = new Traverse[Option] {
	override def traverse[G[_],A,B](oa: Option[A])(f: A => G[B])(implicit G: Applicative[G]): G[Option[B]] =
		oa match {
			case Some(a) => G.map(f(a))(Some(_))
			case None    => G.unit(None)
		}
}

val treeTraverse = new Traverse[Tree] {
	override def traverse[G[_],A,B](ta: Tree[A])(f: A => G[B])(implicit G: Applicative[G]): G[Tree[B]] =
		G.map2(f(ta.head), listTraverse.traverse(ta.tail)(a => traverse(a)(f)))(Tree(_, _))
}

//12.7 使用Traverse
//ex:12.14 使用traverse[F]里的traverse方法实现map
//The simplest possible `Applicative` we can use is `Id`:
type Id[A] = A
//We already know this forms a `Monad`, so it's also an applicative functor:
val idMonad = new Monad[Id] {
      def unit[A](a: => A) = a
      override def flatMap[A,B](a: A)(f: A => B): B = f(a)
    }

//We can now implement `map` by calling `traverse`, picking `Id` as the `Applicative`:
    def map[A,B](fa: F[A])(f: A => B): F[B] = traverse[Id, A, B](xs)(f)(idMonad)
//This implementation is suggestive of laws for `traverse`, since we expect this implementation to obey the usual functor laws. See the chapter notes for discussion of the laws for `Traverse`.

//Note that we can define `traverse` in terms of `sequence` and `map`, which means that a valid `Traverse` instance may define `sequence` and `map`, or just `traverse`: 
trait Traverse[F[_]] extends Functor[F] {
      def traverse[G[_]:Applicative,A,B](fa: F[A])(f: A => G[B]): G[F[B]] = sequence(map(fa)(f))
      def sequence[G[_]:Applicative,A](fga: F[G[A]]): G[F[A]] = traverse(fga)(ga => ga)
      def map[A,B](fa: F[A])(f: A => B): F[B] = traverse[Id, A, B](fa)(f)(idMonad)
}

//
trait Traverse[F[_]] extends Functor[F]{
	def traverse[G[_],A,B](fa:F[A])(f:A=>G[B])(implicit G:Applicative[G]):G[F[B]] = sequence(map(fa)(f))
	def sequence[G[_],A](fga:F[G[A]])(implicit G:Applicative[G]):G[F[A]]=traverse(fga)(ga=>ga)
	def map[A,B](fa:F[A])(f:A=>B):F[B]=???
}


//12.7.1 从monoid到可应用函子
//示例12.8 将一个Monoid转变成一个Applicative
type Const[M,B] = M
implicit def monoidApplicative[M](M:Monoid[M])=
	new Applicative[({type f[x]=Const[M,x]}) #f]{
		def unit[A](a: =>A):M = M.zero
		def map2[A,B,C](m1:M,m2:M)(f:(A,B)=>C):M=M.op(m1,m2)
	}
trait Traverse[F[_]] extends Functor[F] with Foldable[F]{
	def foldMap[A,M](as:F[A])(f: A=>M)(mb: Monoid[M]):M= traverse[({type f[x]=Const[M,x]})#f,A,Nothing](as)(f)(monoidApplicative(mb))}

//ex:12.15 
//It's because `foldRight`, `foldLeft`, and `foldMap` don't give us any way of constructing a value of the foldable type. In order to `map` over a structure, you need the ability to create a new structure (such as `Nil` and `Cons` in the case of a `List`). `Traverse` is able to extend `Functor` precisely because a traversal preserves the original structure. 
An example of a Foldable that is not a functor:
case class Iteration[A](a: A, f: A => A, n: Int) {
	def foldMap[B](g: A => B)(M: Monoid[B]): B = {
		def iterate(n: Int, b: B, c: A): B = if (n <= 0) b else iterate(n-1, g(c), f(a))
		iterate(n, M.zero, a)
	}
}
//This class conceptually represents a sequence of `A` values, generated by repeated function application starting from some seed value. But can you see why it's not possible to define `map` for this type?

//12.7.2 带状态的遍历
//示例12.9 zipWithIndx
def zipWithIndex[A](ta:F[A]):F[(A,Int)] = traverseS(ta)((a:A)=>(for {i<-get[Int]; _ <-set(i+1)}yield (a,i))).run(0)._1

//示例12.10 toList
def toList[A](fa:F[A]):List[A] = traverseS(fa)((a:A)=>(for{as<-get[List[A]]; _ <-set(a::as)}yield())).run(Nil)

//示例12.10 分解mapAccum函数
def mapAccum[S,A,B](fa:F[A],s:S)(f:(A,S)=>(B,S)):(F[B],S)=
	traverseS(fa)((a:A)=>(for {s1<-get[S];(b,s2)=f(a,s1); _ <- set(s2)} yield b)).run(s)
	override def toList[A](fa:f[A]):List[A] = mapAccum(fa,List[A]())((a,s)=>((),a::s))._2.reverse
	def zipWithIndex[A](fa:F[A]):F[(A,Int)]=mapAccum(fa,0)((a,s) =>((a,s),s+1))._1
}

//ex:12.16 用mapAccum实现reverse
def reverse[A](fa: F[A]): F[A] = mapAccum(fa, toList(fa).reverse)((_, as) => (as.head, as.tail))._1

//ex:12.17 用mapAccum实现foldleft
override def foldLeft[A,B](fa: F[A])(z: B)(f: (B, A) => B): B = mapAccum(fa, z)((a, b) => ((), f(b, a)))._2

//12.7.3 组合可遍历结构
//实例:12.12 组合和两个不同的数据类型 zip
def zip[A,B](fa:F[A],fb:F[B]):F[(A,B)] = 
	(mapAccum(fa,toList(fb)){case (a,Nil)=>sys.error("zip:Incompatible shapes.") ; case (a,b::bs)=>((a,b),bs)})._1
//实例:12.13 更灵活的zip实现	
def zipL[A,B](fa:F[A],fb:F[B]):F[A,Option[B]]=	
	(mapAccum(fa,toList(fb)){case (a,Nil)=>((a,None),Nil) ; case (a,b::bs)=>((a,Some(b)),bs)})._1
def zipR[A,B](fa:F[A],fb:F[B]):F[(Option[A],B)] = 
	(mapAccum(fb,toList(fa)){case (b,Nil) => ((None,b),Nil);case (b,a::as=>((Some(a),b),as)})._1

//12.7.4 遍历融合
//ex:12.18 使用可应用函子实现product
def fuse[G[_],H[_],A,B](fa: F[A])(f: A => G[B], g: A => H[B])(implicit G: Applicative[G], H: Applicative[H]): (G[F[B]], H[F[B]]) =
	traverse[({type f[x] = (G[x], H[x])})#f, A, B](fa)(a => (f(a), g(a)))(G product H)

//12.75 嵌套遍历
//ex:1.19 实现对两个traverse实例的组合  compose
def compose[G[_]](implicit G: Traverse[G]): Traverse[({type f[x] = F[G[x]]})#f] =
	new Traverse[({type f[x] = F[G[x]]})#f] {
		override def traverse[M[_]:Applicative,A,B](fa: F[G[A]])(f: A => M[B]) = self.traverse(fa)((ga: G[A]) => G.traverse(ga)(f))
}

//12.7.6 Monad组合 
//ex:12.20 对两个monad实现组合,其中一个是可遍历
def composeM[G[_],H[_]](implicit G: Monad[G], H: Monad[H], T: Traverse[H]):
	Monad[({type f[x] = G[H[x]]})#f] = new Monad[({type f[x] = G[H[x]]})#f] {
		def unit[A](a: => A): G[H[A]] = G.unit(H.unit(a))
		override def flatMap[A,B](mna: G[H[A]])(f: A => G[H[B]]): G[H[B]] = G.flatMap(mna)(na => G.map(T.traverse(na)(f))(H.join))
}


=========================================================CP13 外部作用和IO
//13.1 分解作用
//示例13.1: 带副作用的程序
case class Player(name:String,score:Int)
def contest(p1:Player,p2:Player):Unit = {
	if (p1.score>p2.score) println(s"${p1.name} is the winner")
	else if (p2.score>p1.score) println(s"${p2.name} is the winner")
	else println("its the draw")}

scala> val p1=new Player("jack",22)			--->p1: Player = Player(jack,22)
scala> val p2=new Player("zieox",99)			--->p2: Player = Player(zieox,99)
scala> contest(p1,p2)					--->zieox is the winner

//对player进行逻辑分解
//step1:计算winner
def winner(p1:Player,p2:Player):Option[Player] ={ 
	if (p1.score < p2.score) Some(p2) 
	else if (p1.score>p2.score) Some(p1)	
	else None
}
//step2:打印winner
def contest2(p1:Player,p2:Player):Unit = winner(p1,p2) match {
	case Some(Player(name,_)) => println(s"$name is the winner")
	case None => println("its a draw")
}
//对contest进行再重构
def winnerMSG(p:Option[Player]):String = {p map{case Player(name,_)=>s"$name is the winner"} getOrElse "its s draw"}
def contest(p1:Player,p2:Player):Unit = println(winnerMSG(winner(p1,p2)))
#每个有副作用的函数里有一个纯函数可以被抽离出来

//13.2 一个简单的IO类型
trait IO{def run:Unit}
def printline(msg:String):IO= new IO{def run=println(msg)}
def contest(p1:Player,p2:Player):Unit =printline(winnerMSG(winner(p1,p2)))	//此时contest是纯函数状态

trait IO{
	def run:Unit 
	def ++(io:IO):IO = new IO{def run = {self.run;io.run}}
}	
object IO{def empty:IO = new IO{def run = ()}}


//13.2.1 处理输入效果	
//示例13.2: 华氏到摄氏温度转换的申明式程序
import scala.io.StdIn
def fahrenheitToCelsius(f:Double)=(f-32)*5.0/9.0
def converter:Unit = {
	println("Enter a temperature in degrees Fahrenheit")
	val d = readLine.toDouble
	println(fahrenheitToCelsius(d))
}
#scala 中 readLine从命令窗中捕捉具有副作用的函数定义
sealed trait IO[A] { self => 
	def run:A
	def map[B](f:A=>B):IO[B] = new IO[B]{def run=f(self.run)}
	def flatMap[B](f:A=>IO[B]):IO[B] = new IO[B]{def run = f(self.run).run}
}

object IO extends Monad[IO]{
	def unit[A](a: =>A):IO[A] = new IO[A]{def run=a}
	def flatMap[A,B](fa:IO[A])(f:A=>IO[B])=fa flatMap f
	def apply[A](a: =>A):IO[A] = unit(a)
}
//编写转换器
def ReadLine:IO[String] = IO{readLine}
def PrintLine(msg:String):IO[Unit] = IO {println(msg)}
def converter:IO[Unit] = for {
	_ <- PrintLine("Enter a temperature in degree fahrenheit")
	d <- ReadLine.map(_.toDouble)
	_ <- PrintLine(fahrenheitToCelsius(d).toString)
} yield ()


//示例13.3: 使用doWhile循环的命令编程
def factorial(n:Int):IO[Int] = for {
	acc <- ref(1)
	_ <- foreachM(1 to n toStream)(i=>acc.modify(_*i).skip)
	result <- acc.get
} yield result

val factorialREPL:IO[Unit] = sequence_(
	IO{println(helpstring)}
	doWhile{IO{readLine}}{line => when (line!="q") {for {n <- factorial(line.Toint) ; _ <- IO{println("factorial: "+n)}} yield()}})

//额外的monad组合子
def doWhile[A](a:F[A])(cond: A => F[Boolean]):F[Unit] = for {a1<-a ; ok<-cond(a1) ; _ <- if(ok) doWhile(a)(cond) else unit(())} yield()
def forever[A,B](a:F[A]):F[B] = {lazy val t:F[B]=forever(a) ; a flatMap (_ => t)}
def foldM[A,B](l:Stream[A])(z:B)(f:(B,A)=>F[B]):F[B] = 
	l match {
		case h #:: t =>f(z,h) flatMap (z2=>foldM(t)(z2)(f))
		case _ => unit(z)
	}		
def foldM_[A,B](l:Stream[A])(z:B)(f:(B,A)=>F[B]):F[Unit] = skip{foldM(l)(z)(f)}
def foreachM[A](l:Stream[A])(f:A=>F[Unit]):F[Unit] = foldM_(1)(())((u,a)=>skip(f(a)))

//13.2.2 简单IO类型的优缺点 P194

//13.3 避免栈溢出 StackOverflowError
val p = IO.forever(PrintLine("Still going..."))
def flatMap[B](f:A=>IO[B]):IO[B] = new IO[B]{def run = f(self.run).run}		#StackOverflowError

//13.3.1 将一个控制流转化为数据构造子 P195 
//示例13.4: 构建一个新的IO类型
sealed trait IO[A]{
	def flatMap[B](f:A=>IO[B]):IO[B] = flatMap(this,f)
	def map[B](f: A=>B):IO[B] = flatMap(f andThen (return(_)))
}
case class Return[A](a:A) extends IO[A]
case class Suspend[A](resume:() =>A) extends IO[A]
case class FlatMap[A,B](sub:IO[A],k:A => IO[B]) extends IO[B]


def run[A](io:IO[A]):A = io match{
	case Return(a)=>a
	case Suspend(r)=>r()
	case FlatMap(x,f)=>x match {
		case Return(a)=>run(f(a)) 
		case Suspend(r)=>run(f(r()))
		case FlatMap(y,g) => run(y flatMap (a=>g(a) flatMap f))
	}
}

//13.3.2 Trampolining: 栈溢出的通用解决方式
//ex:
val f = (x:Int) => x
val g = List.fill(1000000)(f).foldLeft(f)(_compose_)
scala> g(42)						--->java.lang.StackOverflowError
val f:Int => IO[Int] = (x:Int) => Return(x)
val g = List.fill(1000000)(f).foldLeft(f){(a,b)=> x =>Suspend(()=>a(x).flatMap(b))}
scala> val x1 = run(g(0))				---> x1:Int = 0
scala> val x2 = run(g(42))				---> x2:Int = 42

//change_name
sealed trait TailRec[A]{
	def flatMap[B](f:A=>TailRec[B]):TailRec[B] = flatMap(this,f)
	def map[B](f: A=>B): TailRec[B] = flatMap(f andThen (Return(_)))
}
case class Return[A](a:A) extends TailRec[A]
case class Suspend[A](resume:() =>A) extends TailRec[A]
case class FlatMap[A,B](sub:TailRec[A],k:A => TailRec[B]) extends TailRec[B]
#使用TailRec比直接的函数调用慢一些,但好处是可预测栈的使用。

//13.4 一个更微妙的IO类型
//示例13.5:定义Async类型
sealed trait Async[A]{
	def flatMap[B](f:A=>Async[B]):Async[B] = FlatMap(this,f)
	def map[B](f:A=>B):Async[B] = flatMap(f andThen (Return(_)))
}
case class Return[A](a:A) extends Async[A]
case class Suspend[A](resume:Par[A]) extends Async[A]
case class FlatMap[A,B](sub:Async[A],k:A=>Async[B]) extends Async[B]

//依赖一个单独的尾递归step函数来关联FlatMap构造子
def step[A](async:Async[A]):Async[A] = async match {
	case FlatMap(FlatMap(x,f),g)=>step(x flatMap (a=>f(a) flatMap g))
	case FlatMap(Return(x),f)=>step(f(x))
	case _ =>async
}

def run[A](async:Async[A]):Par[A]=step(async) match {
	case Return(a) => Par.unit(a)
	case Suspend(r) => Par.flatMap(r)(a=>run(a))
	case FlatMap(x,f) => x match {
		case Suspend(r) => Par.flatMap(r)(a=>run(f(a)))
		case _ => sys.error("impossible;`step` eliminates these cases")
	}
}

sealed trait Free[F[_],A]
case class Return[F[_],A](a:A) extends Free[F,A]
case class Suspend[F[_],A](a:A) extends Free[F,A]
case class FlatMap[F[_],A,B](s:Free[F,A],f:A=>Free[F,B]) extends Free[F,B]

//TailRec和Async时简单的类型别名
type TailRec[A]=Free[Function0,A]
type Async[A]=Free[Par,A]

//13.4.1 合理的monad
//ex:13.1 实现freeMonad
def freeMonad[F[_]]: Monad[({type f[a] = Free[F,a]})#f] =
	new Monad[({type f[a] = Free[F,a]})#f] {
		def unit[A](a: => A) = Return(a)
		def flatMap[A,B](fa: Free[F, A])(f: A => Free[F, B]) = fa flatMap f
	}

//ex:13.2 针对Free[Function0,A] 实现一个特定的尾递归runTrampoline
def runTrampoline[A](a: Free[Function0,A]): A = (a) match {
	case Return(a) => a
	case Suspend(r) => r()
	case FlatMap(x,f) => x match {
		case Return(a) => runTrampoline { f(a) }
		case Suspend(r) => runTrampoline { f(r()) }
		case FlatMap(a0,g) => runTrampoline { a0 flatMap { a0 => g(a0) flatMap f } }
	}
}

//ex:13.3 使用给定的monad[F],对Free[F,A]实现一个泛化的解释器
def run[F[_],A](a: Free[F,A])(implicit F: Monad[F]): F[A] = step(a) match {
	case Return(a) => F.unit(a)
	case Suspend(r) => r
	case FlatMap(Suspend(r), f) => F.flatMap(r)(a => run(f(a)))
	case _ => sys.error("Impossible, since `step` eliminates these cases")
}

//13.4.2 一个支持控制台I/O的monad
//示例13.6:创建Console类型
sealed trait Console[A]{
	def toPar:Par[A]
	def toThunk: () => A
}
case object ReadLine extends Console[Option[String]]{
	def toPar=Par.lazyUnit(run)
	def toThunk = ()=>run
	def run: Option[String]=try Some(readLine()) catch {case e:Exception=>None}
}
case class PrintLine(line:String) extends Console[Unit] {
	def toPar = Par.lazyUnit(println(line))
	def toThunk = () => println(line)
}

//使用Free和Suspend构造子
object Console{
	type ConsoleIO[A] = Free[Console,A]
	def readLn:ConsoleIO[Option[String]]=Suspend(ReadLine)
	def printLn(line:String):ConsoleIO[Unit]=Suspend(PrintLine(line))
}

val f1:Free[Console,Option[String]] = for {
	_ <- pritnLn("i can only interactive with the console")
	ln <- readLn
} yield ln

//Monad[Console]
sealed trait Console[A]{
	def flatMap[B](f:A=>Console[B]):Console[B] = this match{
		case ReadLine => ???
		case PrintLine(s) => ???
	}
}
//
trait Translate[F[_],G[_]] {def apply[A](f:F[A]):G[A]}	//任意F[A]到G[A]的转化
type ~>[F[_],G[_]] = Translate[F,G]
val consoleToFunction0 = new (Console~>Function0){def apply[A](A:Console[A])=a.toThunk}
val consoleToPar = new (Console~>Par){def apply[A](a:Console[A])=a.toPar}
def runFree[F[_],G[_],A](free:Free[F,A])(t:F~>G)(implicit G:Monad[G]):G[A] =
	step(free) match {
		case Return(a) => G.unit(a)
		case Suspend(r) => t(r)
		case FlatMap(Suspend(r),f) => G.FlatMap(t(r))(a=>runFree(f(a))(t))
		case _ => sys.error("Impossible; `step` eliminates these cases")
}


//
def runConsoleFunction0[A](a:Free[Console,A]): () => A = runFree[Console,Function0,A](a)(consoleToFunction0)
def runConsolePar[A](a:Free[Console,A]):Par[A] = runFree[Console,Par,A](a)(consoleToPar)
implicit val function0Monad = new Monad[Function0]{
	def unit[A](a: =>A) = () => a
	def flatMap[A,B](a:Function0[A])(f:A=>Function0[B]) = ()=>f(a())()
}
implicit val parMonad = new Monad[Par]{
	def unit[A](a: =>A) = Par.Unit(a)
	def flatMap[A,B](a:Function0[A])(f:A=>Par[B]) = Par.fork{Par.flatMap(a)(f)}
}

//ex:13.4 实现一个栈安全的runConsole
def translate[F[_],G[_],A](f: Free[F,A])(fg: F ~> G): Free[G,A] = {
	type FreeG[A] = Free[G,A]
	val t = new (F ~> FreeG) {def apply[A](a: F[A]): Free[G,A] = Suspend { fg(a) }}
	runFree(f)(t)(freeMonad[G])
}
def runConsole[A](a: Free[Co nsole,A]): A =runTrampoline { translate(a)(new (Console ~> Function0) {def apply[A](c: Console[A]) = c.toThunk})}

//13.4.3 纯解释器
//示例13.7 创建ConsoleReader类型
case class ConsoleReader[A](run:String => A){
	def map[B](f:A=>B):ConsoleReader[B]=ConsolderReader(r=>f(run(r)))
	def flatMap[B](f:A=>ConsoleReader[B]):ConsoleReader[B] = ConsoleReader(r=>f(run(r)).run(r))
}
object ConsoleReader{
	implicit val monad = new Monad[ConsoleReader]{
		def unit[A](a: =>A) = ConsoleReader(_ =>a)
		def flatMap[A,B](ra:ConsoleReader[A])(f:A=>ConsoleReader[B]) = ra faltMap f
	}
}


//13.5 非阻塞和异步I/O
def p:ConsoleIO[Unit] = for {
	_ <- pritLn("whats your name")
	n <- readLn
	_ <- n match {
		case Some(n) => printLn(s"hello , $n")
		case None =>printLn(s"Fine, be that way")
	}
} yield ()

trait Source{def readBytes(numBytes:Int,callback:Either[Throwable,Array[Byte]]=>Unit):Unit}
trait Future[+A]{private def apply(k:A=>Unit)}
type Par[+A] = ExecutorService => Future[A]
def async[A](run:(A=>Unit) => Unit):Par[A] = es => new Future{def apply(k:A=>Unit) = run(k)}
def nonblockingRead(source:Source,numBytes:Int):Par[Either[Throwable,Array[Byte]]] => async {(cb:Either[Throwable,Array[Byte]]=>Unit) => source.readBytes(numBytes,cb)}

def readPar(source:Source,numBytes:Int):Free[Par,Either[Throwable,Array[Byte]]] = Suspend(nonblockingRead(source,numBytes))

//ex:13.5 java.nio 实现 异步读取
import java.nio._
import java.nio.channels._
def read(file: AsynchronousFileChannel,fromPosition: Long,numBytes: Int): Par[Either[Throwable, Array[Byte]]] =
	Par.async { (cb: Either[Throwable, Array[Byte]] => Unit) =>
		val buf = ByteBuffer.allocate(numBytes)
		file.read(buf, fromPosition, (), new CompletionHandler[Integer, Unit] {
			def completed(bytesRead: Integer, ignore: Unit) = {
				val arr = new Array[Byte](bytesRead)
				buf.slice.get(arr, 0, bytesRead)
				cb(Right(arr))
			}
			def failed(err: Throwable, ignore: Unit) = cb(Left(err))
		})
	}

//13.6 一个通用的IO类型
//13.6.1 最终的main程序
//示例13.8 将副作用转变成作用
abstract class App{
	import java.util.concurrent._
	def unsafePerformIO[A](a:IO[A])(pool:ExecutorService):A = Par.run(pool)(run(a)(parMonad))
	def main(args:Array[String]):Unit = {	
		val pool = Executors.fixedThreadPool(8)
		unsafePerformIO(pureMain(args))(pool)
	}
	def pureMain(args:IndexedSeq[String]):IO[Unit]
}

//13.7 为什么IO类型不足以支持撑流式I/O
trait Files[A]
case class ReadLines(file:String) extends Files[List[String]] 
case class WriteLines(file:String,lines:List[String]) extends Files[Unit]
val p:Free[Files,Unit] = for {
	lines <- Suspend {(ReadLines("fahrenheit.txt"))}
	cs = lines.map(s=>fahrenheitToCelsius(s.toDouble).toString)
	_ <- Suspend{WriteLines("celsius.txt",cs)}
}yield ()

trait Files[A]
case class OpenRead(file:String) extends Files[HandleR]
case class OpenWrite(file:String) extends Files[HandleW]
case class ReadLine(h:HandleR) extends Files[Option[String]]
case class WriteLine(h:HandleW,line:String) extends Files[Unit]
trait HandleR
trait HandleW

//make the loop
def loop(f:HandleR,c:HandleW):Free[Files,Unit] = for {
	line <- Suspend{ReadLine(f)}
	_ <- line match {
		case None => IO.unit(())
		case Some(s) =>Suspend{ WriteLine(fahrenheitToCelsius(s.toDouble))} flatMap (_ =>loop(f,c))
	}
} yield b

def convertFiles = for {
	f <- Suspend(OpenRead("fahrenheit.txt"))
	c <- Suspend(OpenWrite("celsius.txt"))
	_ <- loop(f,c)
} yield ()


def movingAvg(n:Int)(l:List[Double]): List[Double]
cs = movingAvg(5)(lines.map(s=>fahrenheitToCelsius(s.toDouble))).map(_.toString)


=========================================================CP14 局部作用和可变状态
//14.1 纯函数的可变状态
#引用透明定义:
	#倘若表达式e是引用透明的,那么对于所有程序p而言,其中e都可以用其求值后的结果替换,且不影响p的原始含义。
	#倘若一个函数f是纯粹的,那么表达式f(x)对于所有引用透明的x而言也是引用透明的。
//示例14.1 可变数组的product
def quicksort(xs:List[Int]):List[Int] = if (xs.isEmpty) xs else {
	val arr = xs.toArray
	def swap(x:Int,y:Int)={
		val tmp = arr(x)
		arr(x) = arr(y)
		arr(y) = tmp
	}
	def partition(n:Int,r:Int,pivot:Int) = {
		val pivotVal = arr(pivot)
		swap(pivot,r)
		var j = n
		for (i<- n until r) if (arr(i) < pivotVal){
			swap(i,j)
			j += 1
		}
		swap(j,r)
		j
	}
	def qs(n:Int,r:Int):Unit = if (n<r) {
		val pi = partition(n,r,n+(r-n)/2)
		qs(n,pi-1)
		qs(pi+1,r)
	}
	qs(0,arr.length-1)
	arr.toList
}

//14.2 一种限制副作用范围的数据类型
//14.2.1 受限可变性的语言表达 p212
//示例14.2 新数据类型ST
sealed trait ST[S,A]{ self=>
	protected def run(s:S):(A,S)
	def map[B](f:A=>B):ST[S,B] = new ST[S,B]{def run(s:S)={val (a,s1)=self.run(s) ; (f(a),s1)}}
	def flatMap[B](f:A=>ST[S,B]):ST[S,B]= new ST[S,B]{def run(s:S)={val (a,s1)=self.run(s) ; f(a).run(s1)}}
}
object ST{
	def apply[S,A](a: =>A)={
		lazy val memo =a
		new ST[S,A]{def run(s:S)=(memo,s)}
	}
}

//14.2.2 一种可变引用的代数表达
sealed trait STRef[S,A]{
	protected var cell:A
	def read:ST[S,A]=ST(cell)
	def write(a:A):ST[S,Unit] = new ST[S,Unit]{def run(s:S) = {cell=a ; ((),s)}}
}
object STRef{def apply[S,A](a:A):ST[S,STRef[S,A]]=ST(new STRef[S,A]{val cell=a})}
for{
	r1<-STRef[Nothing,Int](1)
	r2<-STRef[Nothing,Int](1)
	x <-r1.read
	y <-r2.read
	_ <-r1.write(y+1)
	_ <-r2.write(x+1)
	a <-r1.read
	b <-r2.read
}yield(s,b)

//14.2.3 执行修改状态的行为
trait RunableST[S,A]{def apply[S]:ST[S,A]}
val p = new RunnableST[(Int,Int)]{
	def apply[S] = for {
		r1 <- STRef(1)
		r2 <- STRef(2)
		x <- r1.read
		y <- r2.read
		_ <- r1.write(y+1)
		_ <- r2.write(x+1)
		a <- r1.read
		b <- r2.read
	}yield(a,b)
}

object ST {
	def apply[S,A](a: =>A) ={
		lazy val memo = a
		new ST[S,A]{def run(s:S) = (memo,s)}
	}
	def runST[A](st:RunnableST[A]):A=st.apply[Unit].run(())._1
}

val ref = ST.runST(new RunnableST[STRef[_,Int]]{def apply[S]=for{r1<-STRef(1)}yield r1})

//14.2.4 可变数组
//示例14.3 一个数组的STmonad
sealed trait class STArray[S,A](implicit manifest:Manifest[A]){
	protected def value:Array[A]
	def size:ST[S,Int]=ST(value.size)
	def write(i:Int,a:A):ST[S,Unit] = new ST[S,Unit]{def run(s:S) = {value(i) = a ; ((),s)}}
	def read(i:Int):ST[S,A]=ST(value(i))
	def freeze:ST[S,List[A]] = ST(value.toList)
}
object STArray{def apply[S,A:Manifest](sz:Int,v:A):ST[S,STArray[S,A]] = new STArray[S,A]{lazy val value = Array.fill(sz)(v)}}

//ex:14.1 实现fill
def fill(xs: Map[Int,A]): ST[S,Unit] = xs.foldRight(ST[S,Unit](())) {case ((k, v), st) => st flatMap (_ => write(k, v))}

//14.2.5 一个纯函数的in-place快排实现
def swap[S](i:Int,j:Int):ST[S,Unit] = for {
	x <- read(i)
	y <- read(j)
	_ <- write(i,y)
	_ <- write(j,x)
}yield ()

 //scala风格的或者说纯函数式风格的快速排序
def quicksort(xs: List[Int]): List[Int] =
	if (xs.isEmpty) xs else ST.runST(new RunnableST[List[Int]] {
		def apply[S] = for {
			arr    <- STArray.fromList(xs)
			size   <- arr.size
			_      <- qs(arr, 0, size - 1)
			sorted <- arr.freeze
		} yield sorted})
	}

//14.3 纯粹性是相对于上下文的
case class foo(s:String)
scala> val b = foo("hello") == foo("hello")				--->b: Boolean = true
scala> val c = foo("hello") eq foo("hello")				--->c: Boolean = false
scala> val x =foo("hello")						--->x: foo = foo(hello)
scala> val s = x eq x							--->s: Boolean = true
#用eq测试引用相等性
//一个更抽象的引用透明性的定义
#如果说在程序p中每个出现的表达式e都被其求值的结果给替换,且对p不造成任何影响,我们可以说e对于p而言是引用透明的。
#求值:简化到一种普通形态

//14.3.1 副作用是什么 p221


=========================================================CP15 流式处理与增量IO
//15.1 命令式I/O的问题示例
//示例15.1: 用命令式风格计算行数
def linesGt40k(filename:String):IO[Boolean] = IO {
	val src = io.Source.fromFile(filename)
	try{
		var count = 0
		val lines:Iterator[String] = src.getLines
		while (count <= 40000 && lines.hasNext){lines.next ; count +=1}
		count > 40000
	}
	finally src.close
}

lines.zipWithIndex.exists(_._2 + 1 >= 40000)
lines.filter(!_.trim.isEmpty).zipWithIndex.exists(_._2 + 1 >= 40000)
lines.filter(!_.trim.isEmpty).take(40000).map(_.head).indexOfSlice("asdfghjfdsasdfgas".toList)
//延迟I/O
def lines(filename:String):IO[Stream[String]] = IO {
	val src = io.Source.fromFile(filename)
	src.getLines.toStream append {src.close ; Stream.empty}
}

//15.2 一个简单的流转换器
#流指代某种序列,可能是延迟产生或由外部提供的,流转换器指定乐一种流到另一种流的转换方式。
//示例15.2 Process数据类型
sealed trait Process[I,O]
case class Emit[I,O](head:O,tail:Process[I,O]=Halt[I,O]()) extends Process[I,O]
case class Await[I,O](recv:Option[I] => Process[I,O]) extends Process[I,O]
case class Halt[I,O]() extends Process[I,O]

def apply(s:Stream[I]):Stream[O] = this match {
	case Halt() => Stream()
	case Await(recv) => s match {
		case h #:: t => recv(Some(h))(t)
		case xs => recv(None)(xs)
	}
	case Emit(h,t) => h #:: t(s)
}

//15.2.1 创建Process P227
def liftOne[I,O](f:I=>O):Process[I,O] = Await{case Some(i) => Emit(f(i)) ; case None => Halt()}
val p = liftOne((x:Int) => x*2)
val xs = p(Stream(1,2,3)).toList

def repeat:Process[I,O] = {
	def go(p:Process[I,O]):Process[I,O] = p match {
		case Halt() => go(this)
		case Await(recv) => Await{case None => recv(None) ; case i => go(recv(i))}
		case Emit(h,t) => Emit(h,go(t))
	}
	go(this)
}

def lift[I,O](f:I=>O):Process[I,O] = liftOne(f).repeat
val units = Stream.continually(())
val ones = lift((_:Unit)=>1)(units)
def filter[I](p:I=>Boolean):Process[I,I] = Await[I,I]{case Some(i) if p(i) => Emit(i) ; case _ => Halt()}.repeat

val even = filter((x:Int) => x%2==0)
val evens = even(Stream(1,2,3,4)).toList
def sum:Process[Double,Double] = {
	def go(acc:Double):Process[Double,Double] = Await{case Some(d)=>Emit(d+acc,go(d+acc)) ; case None=>Halt()}
	go(0.0)
}

//ex:15.1 实现take,drop,takeWhile,dropWhile
def take[I](n: Int): Process[I,I] =if (n <= 0) Halt() else await(i => emit(i, take[I](n-1)))
def drop[I](n: Int): Process[I,I] =if (n <= 0) id else await(i => drop[I](n-1))
def takeWhile[I](f: I => Boolean): Process[I,I] = await(i => if (f(i)) emit(i, takeWhile(f))else Halt())
def dropWhile[I](f: I => Boolean): Process[I,I] = await(i =>if (f(i)) dropWhile(f) else emit(i,id))

//ex:15.2 实现count  f(count(Stream("a","bb","cc"))) -> Stream(1,2,3)
def count[I]: Process[I,Int] =
	lift((i: I) => 1.0) |> sum |> lift(_.toInt)	
	/* For comparison, here is an explicit recursive implementation. */
	def count2[I]: Process[I,Int] = {
		def go(n: Int): Process[I,Int] =
			await((i: I) => emit(n+1, go(n+1)))
			go(0)
	}

//ex:15.3 实现mean
def mean: Process[Double,Double] = {
	def go(sum: Double, count: Double): Process[Double,Double] =
		await((d: Double) => emit((sum+d)/(count+1), go(sum+d,count+1)))
		go(0.0, 0.0)
	}

//ex:15.4 实现Loop
def sum2: Process[Double,Double] = loop(0.0)((d:Double, acc) => (acc+d,acc+d))
def count3[I]: Process[I,Int] = loop(0)((_:I,n) => (n+1,n+1))

//15.2.2 组合和追加处理
def |>[O2](p2: Process[O,O2]): Process[I,O2] = {
	p2 match {
		case Halt() => Halt()
		case Emit(h,t) => Emit(h, this |> t)
		case Await(f) => this match {
			case Emit(h,t) => t |> f(Some(h))
			case Halt() => Halt() |> f(None)
			case Await(g) => Await((i: Option[I]) => g(i) |> p2)
		}
	}
}

def map[O2](p2:Process[O,O2]):Process[I,O2] = this |> lift(f)

def ++ (p: =>Process[I,O]):Process[I,O] = this match {
	case Halt() => Halt()
	case Emit(h,t)=>Emit(h,t++p)
	case Await(recv) => Await(recv andThen (_ flatMap f))
}

def flatMap[O2](f:O=>Process[I,O2]):Process[I,O2] = this match{
	case Halt() =>Halt()
	case Emit(h,t)=>f(h) ++ t.flatMap(f)
	case Await(recv) => Await(recv andThen (_ flatMap f))
}

def monad[I]:Monad[({type f[X]=Process[I,x]})#f] = 
	new Monad[({type f[X]=Process[I,x]})#f]{
		def unit[O](o: =>O):Process[I,O]=Emit(o)
		def flatMap[O,O2](p:Process[I,O])(f:O=>Process[I,O2]):Process[I,O2] = p flatMap f
}

//ex:15.6 实现zipWithIndex
def zipWithIndex: Process[I,(O,Int)] = this zip (count map (_ - 1))
//ex:15.7 尝试从sum和count中抽象出来的组合子实现mean
def zip[A,B,C](p1: Process[A,B], p2: Process[A,C]): Process[A,(B,C)] =
	(p1, p2) match {
		case (Halt(), _) => Halt()
		case (_, Halt()) => Halt()
		case (Emit(b, t1), Emit(c, t2)) => Emit((b,c), zip(t1, t2))
		case (Await(recv1), _) => Await((oa: Option[A]) => zip(recv1(oa), feed(oa)(p2)))
		case (_, Await(recv2)) => Await((oa: Option[A]) => zip(feed(oa)(p1), recv2(oa)))
	}
	
def feed[A,B](oa: Option[A])(p: Process[A,B]): Process[A,B] =
	p match {
		case Halt() => p
		case Emit(h,t) => Emit(h, feed(oa)(t))
		case Await(recv) => recv(oa)
	}

//ex:15.8 实现exist的多种方式
def exists[I](f: I => Boolean): Process[I,Boolean] = lift(f) |> any
/* Emits whether a `true` input has ever been received. */
def any: Process[Boolean,Boolean] = loop(false)((b:Boolean,s) => (s || b, s || b))
/* A trimmed `exists`, containing just the final result. */
def existsResult[I](f: I => Boolean) = exists(f) |> takeThrough(!_) |> dropWhile(!_) |> echo.orElse(emit(false))
/* Like `takeWhile`, but includes the first element that tests false.*/
def takeThrough[I](f: I => Boolean): Process[I,I] = takeWhile(f) ++ echo
/* Awaits then emits a single value, then halts. */
def echo[I]: Process[I,I] = await(i => emit(i))

//15.2.3 处理文件
//示例15.3: 使用Process处理文件
def processFile[A,B](f:java.io.File,p:Process[String,A],z:B)(g:(B,A)=>B):IO[B]=IO{
	def go(ss:Iterator[String],cur:Process[String,A],acc:B):B=
		cur match {
			case Halt() => acc
			case Await(recv) => val next = if (ss.hasNext) recv(Some(ss.next)) else recv(None)
							go(ss,next,acc)
			case Emit(h,t) => go(ss,t,g(acc,h))
		}
	val s = io.Source.fromFile(f)
	try go(s.getLines,p,z)
	finally s.close
}

//ex:15.9 实现 
def toCelsius(fahrenheit:Double):Double = (5.0/9.0)*(fahrenheit - 32.0)
def convertFahrenheit: Process[String,String] =
	filter((line: String) => !line.startsWith("#")) |>
	filter(line => line.trim.nonEmpty) |>
	lift(line => toCelsius(line.toDouble).toString)
	def toCelsius(fahrenheit: Double): Double = (5.0 / 9.0) * (fahrenheit - 32.0)

//15.3 可扩展的处理类型
//示例15.4:可扩张的Process类型
trait Process[F[_],O]
object Process{
	case class Await[F[_],A,O](req:F[A],recv:Either[Throwable,A] => Process[F,O]) extends Process[F,O]
	case class Emit[F[_],O](head:O,tail:Process[F,O]) extends Process[F,O]
	case object End extends Exception
	case object Kill extends Exception
}

//示例15.5:onHalt 和 ++ 函数
def onHalt(f:Throwable=>Process[F,O]):Process[F,O] = this match{
	case Halt(e) => Try(f(e))
	case Emit(h,t) => Emit(h,t.onHalt(f))
	case Await(req,recv) => Await(req,recv andThen (_.onHalt(f)))
}
def ++(p: =>Process[F,O]):Process[F,O] = this.onHalt{case End => p ; case err =>Halt(err)}
//实现帮助Try函数
def Try[F[_],A,O](p: =>Process[F,O]):Process[F,O] = try p catch{case e:Throwable => Halt(e)}
//引入帮助函数await
def await[F[_],A,O](req:F[A])(recv:Either[Throwable,A]=>Process[F,O]):Process[F,O] = Await(req,rcv)
//use ++ make flatMap
def flatMap[O2](f:O=>Process[F,O2]):Process[F,O2] = 
	this match {
		case Halt(err) => Halt(err)
		case Emit(o,t) => Try(f(o)) ++ t.flatMap(f)
		case Await(req,recv) => Await(req,recv andThen (_ flatMap f))
}

//15.3.1 来源
case class Await[A,O](req:IO[A],recv:Either[Throwable,A] => Process[IO,O]) extends Process[IO,O]
//示例15.6:runLog函数
def runLog[O](src:Process[IO,O]):IO[IndexedSeq] = IO {
	val E = java.util.concurrent.Executors.newFixedThreadPool(4)
	def go(cur:Process[IO,O],acc:IndexedSeq[O]):IndexedSeq[O] =
		cur match {
			case Emit(h,t) => go(t,acc :+ h)
			case Halt(End) => acc
			case Halt(err) => throw err
			case Await(req,recv) => 
				val next = try recv(Right(unsafePerformIO(req)(E))) catch {case err:Throwable=>recv(Left(err))}
				go(next,acc)
		}
	try go(src,IndexedSeq())
	finally E.shutdown
}

//遍历文件所有行
import java.io.{BufferedReader,FileRead}
val p:Process[IO,String] =
	await(IO(new BufferedReader(new FileReader("lines.txt")))){
		case Right(b) =>
			lazy val next:Process[IO,String] = await(IO(b.readLine)){
				case Left(e) => await(IO(b.close))(_ => Halt(e))
				case Right(line) => if(line eq null) Halt(End) else Emit(line,next)
			}
			next
		case Left(e) => Halt(e)
	}

//ex:15.10 实现runLog
def runLog(implicit F: MonadCatch[F]): F[IndexedSeq[O]] = {
	def go(cur: Process[F,O], acc: IndexedSeq[O]): F[IndexedSeq[O]] =
		cur match {
			case Emit(h,t) => go(t, acc :+ h)
			case Halt(End) => F.unit(acc)
			case Halt(err) => F.fail(err)
			case Await(req,recv) => F.flatMap (F.attempt(req)) { e => go(Try(recv(e)), acc) }
		}
	go(this, IndexedSeq())
}

//15.3.2 保证资源安全
def onComplete(p: =>Process[F,O]):Process[F,O] = this.onHalt{case End => p.asFinalizer ; case err => p.asFinalizer ++ Halt(err1)}
def asFinalizer:Process[F,O] = this match{
	case Emit(h,t) => Emit(h,t.asFinalizer)
	case Halt(e) => Halt(e)
	case Await(req,recv) => await(req){case Left(Kill) => this.asFinalizer ; case x => recv(x)}
}
//结合onComplete和asFinalizer
def resource[R,O](acquire:IO[R])(use:R=>Process[IO,O])(release: R=>Process[IO,O]):Process[IO,O] = 
	await[IO,R,O](acquire)(r=>use(r).onComplete(release(r)))

//ex:15.11 实现lines & eval
def lines(filename: String): Process[IO,String] =
	resource{ IO(io.Source.fromFile(filename)) }
	{ src =>
		lazy val iter = src.getLines // a stateful iterator
		def step = if (iter.hasNext) Some(iter.next) else None
		lazy val lines: Process[IO,String] = eval(IO(step)).flatMap {case None => Halt(End);case Some(line) => Emit(line, lines)}
		lines
	}
	{ src => eval_ { IO(src.close) } }
/* Exercise 11: Implement `eval`, `eval_`, and use these to implement `lines`. */
def eval[F[_],A](a: F[A]): Process[F,A] = await[F,A,A](a) {case Left(err) => Halt(err) ; case Right(a) => Emit(a, Halt(End))}
/* Evaluate the action purely for its effects. */
def eval_[F[_],A,B](a: F[A]): Process[F,B] = eval[F,A](a).drain[B]

//15.3.3 单一输入过程
case class Is[I](){sealed trait f[X] ; val Get = new f[I]}
type Process1[I,O] = Process[Is[I]#f,O]
case class Await[A,O](req:Is[I]#f[A],recv:Either[Throwable,A] => Process[Is[I]#f,O]) extends Process[Is[I]#f,R]

//示例15.7: 类型推导相关的帮助函数
def await1[I,O](recv:I=>Process1[I,O],fallback:Process1[I,O]=halt1[I,O]):Process1[I,O] = 
	Await(Get[I],(e:Either[Throwable,I]) => e match {
		case Left(End) => fallback
		case Left(err) => Halt(err)
		case Right(i) => Try(recv(i))
})
def emit1[I,O](h:O,t1:Process[I,O] = halt1[I,O]):Process1[I,O] = emit(h,t1)
def halt1[I,O]:Process[I,O]=Halt[Is[I]#f,O](End)
def lift[I,O](f:I=>O):Process1[I,O] = await1[I,O](i=>emit(f(i))) repeat
def filter[I](f:I=>Boolean):Process1[I,I] = await[I,I](i=> if (f(i)) emit(i) else halt1) repeat

def |>[O2](p2:Process1[O,O2]):Process[F,O2] = {
	p2 match {
		case Halt(e) => this.kill onHalt {Halt(e) ++ Halt(e2)}
		case Emit(h,t) => Emit(h,this |> t)
		case Await(req,recv) => this match{
			case Halt(err) => Halt(err) |> recv(Left(err))	
			case Emit(h,t) => t |> Try(recv(Right(h)))
			case Await(req0,recv0) => await(req0)(recv0 andThen (_ |> p2))
		}
	}
	def pipe[O2](p2:Process[O,O2]):Process[F,O2]= this |> P2
}	

//示例15.8: kill帮助函数
final def kill[O2]:Process[F,O2] = this match {
	case Await(req,recv) => recv(Left(Kill)).drain.onHalt{
		case Kill => Halt(End)
		case e => Halt(e)
	}
	case Halt(e) => Halt(e)
	case Emit(h,t) => t.kill
}
final def drain[O2]: Process[F,O2] = this match {
	case Halt(e) => Halt(e)
	case Emit(h,t) => t.drain
	case Await(req,recv) => Await(req,recv andThen (_.drain))
}

def filter(f:O=>Boolean):Process[F,O] = this |> Process.filter(f)

//15.3.4 多个输入流
case class T[I,I2](){
	sealed trait f[X]{def get:Either[I=>X,I2=>X]}
	val L = new f[I]{def = Left(identity)}
	val R = new f[I2]{def get = Right(identity)}
}
def L[I,I2]=T[I,I2]().L
def R[I,I2]=T[I,I2]().R

type Tee[I,I2,O] = Process[T[I,I2]#F,O]

//示例15.9: 给Tee的输入用的常规函数
def haltT[I,I2,O]:Tee[I,I2,O] = Halt[T[I,I2]#f,O](End)
def awaitL[I,I2,O](recv:I=>Tee[I,I2,O],fallback: =>Tee[I,I2,O]=haltT[I,I2,O]):Tee[I,I2,O]=
	await[T[I,I2]#f,I2,O](R){
		case Left(End) =>fallback
		case Left(err) => Halt(err)
		case Right(a) => Try(recv(a))
	}
def awaitR[I,I2,O](recv:I=>Tee[I,I2,O],fallback: =>Tee[I,I2,O] = haltT[I,I2,O]):Tee[I,I2,O] = 
	await[T[I,I2]#f,I2,O](R){
		case Left(End) => fallback
		case Left(err) => Halt(err)
		case Right(a) => Try(recv(a))
}
def emitT[I,I2,O](h:O,t1:Tee[I,I2,O] = haltT[I,I2,O]):Tee[I,I2,O] = emit(h,t1)
def zipWith[I,I2,O](f:(I,I2)=>O):Tee[I,I2,O] = awaitL[I,I2,O](i => awaitR (i2=>emitT(f(i,i2)))) repeat
def zip[I,I2]:Tee[I,I2,(I,I2)]=zipWith((_,_))

//示例15.10:tee函数
def tee[O2,O3](p2:Process[F,O2])(t:Tee[O,O2,O3]):Process[F,O3] =
	t match {
		case Halt(e) => this.kill onComplete p2.kill onComplete Halt(e)
		case Emit(h,t) => Emit(h,(this tee p2)(t))
		case Await(side,recv) => side.get match{
			case Left(isO)=>this match{
				case Halt(e) => p2.kill onComplete Halt(e)
				case Emit(o,ot) => (ot tee p2)(Try(recv(Right(o))))
				case Await(reqL,recvL) => await(reqL)(recvL AndThen (this2=>this2.tee(p2)(t)))
			}
		case Right(isO2) => p2 match {
			case Halt(e) => this.kill onComplete Halt(e)
			case Emit(o2,ot) => (this tee ot)(Try(recv(Right(o2)))
			case Await(reqR,recvR) => await(reqR)(recvR andThen (p3=>this.tee(p3)(t)))
		}

	}
}

//15.3.5 去向
//递送函数
type Sink[F[_],O] = Process[F[_],O=>Process[F,Unit]]
def fileW(file:String,append:Boolean=false):Sink[IO,String] = 
	resource[FileWriter,String=>Process[IO,Unit]] 
	{IO{new FileWriter(file,append)}}
	{w=>constant{(s:String)=>eval[IO,Unit](IO(w.write(s)))}}
	{w=>eval_(IO(w.close))}	
def constant[A](a:A):Process[IO,A] = eval[IO,A](IO(a)).repeat
def to[O2](sink:: Sink[F,O]):Process[F,Unit] = join{(this zipWith sink)((o,f)=>f(o))}


//ex:15.12 实现join
def join[F[_],A](p: Process[F,Process[F,A]]): Process[F,A] = p.flatMap(pa => pa)

===>
val converter:Process[IO,Unit] = 
	lines(fahrenheit.txt).
	filter(!_.startsWith("#")).
	map(line=>fahrenheitToCelsius(line.toDouble).toString).
	pipe(intersperse("\n")).
	to(fileW("celsius.txt")).
	drain
final def drain[O2]:Process[F,O2] = this match {
	case Halt(e) => Halt(e)
	case Emit(h,t) => t.drain
	case Await(req,recv) => Await(req,recv andThen (_.drain))

//15.3.6 Effectful 通道
def through[O2](P2:Process[F,O=>Process[F,O2]]):Process[F,O2] = join{(this zipWith p2)((o,f)=>f(o))}
type Channel[F[_],I,O] = Process[F,I=>Process[F,O]]
import java.sql.{Connection,PreparedStatement,ResultSet}
def query(conn:IO[Connection]):Channel[IO,Connection => PreparedStatement,Map[String,Any]]

//15.3.7 动态资源分配(当需要转换某些输入流时需要动态的分配资源)
val convertAll:Process[IO,Unit] = (for{
	out <- fileW("celsius.txt").once
	file <- lines("fahrenheits.txt")
	_ <- lines(file).map(line=>fahrenheitToCelsius(line.toDouble)).flatMap(celsius=>out(celsius.toString))	
} yield()) drain

val convertMultisink:Process[IO,Unit] = (for {
	file <- lines("fahrenheits.txt")
	_ <- lines(file).
	     map(line=>fahrenheitToCelsius(line.toDouble)).
	     map(_ toString).
	     to(fileW(file+".celsius"))
}yield()) drain

val convertMultisink2:Process[IO,Unit] = (for {
	file <- lines("fahrenheits.txt")
	_ <- lines(file).
	     filter(!_.startsWith("#"))
	     map(line=>fahrenheitToCelsius(line.toDouble)).
	     filter(_ >0)
	     map(_ toString).
	     to(fileW(file+".celsius"))
} yield ()) drain

//15.4 应用场景 P244





********************************************************Scala Cook Book*********************************************************
========================================================CP1 String 字符串
//1.1 Testing String Equallity 测试String相等性
scala> val a = "Marisa"					--->a: String = Marisa
scala> val b = "marisa"					--->b: String = marisa
scala> a.equalsIgnoreCase(b)				--->res0: Boolean = true

//1.2. Creating Multiline Strings 
//stripMargin 去边方法
val speech = """Four score and
|seven years ago""".stripMargin

val speech = """Four score and
#seven years ago""".stripMargin('#')

scala> val speech = """Four score and
     | |seven years ago
     | |our fathers""".stripMargin.replaceAll("\n", " ")
		---->speech: String = Four score and seven years ago our fathers

scala> "zieox is a man".stripMargin.replaceAll(" ","-")				--->res0: String = zieox-is-a-man

//1.3. Splitting Strings
//split方法
scala> "hello world".split(" ")							--->res2: Array[String] = Array(hello, world)
scala> "hello world".split(" ").foreach(println)
	hello
	world
scala> val s = "eggs, milk, butter, Coco Puffs"					--->s: String = eggs, milk, butter, Coco Puffs
scala> s.split(",")					--->res3: Array[String] = Array(eggs, " milk", " butter", " Coco Puffs")
scala> s.split(",").map(_.trim)					--->res4: Array[String] = Array(eggs, milk, butter, Coco Puffs)

//1.4. Substituting Variables into Strings
//代入方法
scala> val name = "Fred"						--->name: String = Fred
scala> val age = 33							--->age: Int = 33
scala> val weight = 200.00						--->weight: Double = 200.0
scala> println(s"$name is $age years old, and weighs $weight pounds.")
									--->Fred is 33 years old, and weighs 200.0 pounds.
scala> println(s"Age next year: ${age + 1}")				--->Age next year: 34
scala> println(s"You are 33 years old: ${age == 33}")			--->You are 33 years old: true
scala> case class Student(name: String, score: Int)			--->defined class Student
scala> val hannah = Student("Hannah", 95)				--->hannah: Student = Student(Hannah,95)
scala> println(s"${hannah.name} has a score of ${hannah.score}")	--->Hannah has a score of 95
scala> println(s"$hannah.name has a score of $hannah.score")
								--->Student(Hannah,95).name has a score of Student(Hannah,95).score

scala> val name = "Fred"						--->name: java.lang.String = Fred
scala> val age = 33							--->age: Int = 33
scala> val s = "%s is %d years old".format(name, age)			--->s: String = Fred is 33 years old
scala> println("%s is %d years old".format(name, age))			--->Fred is 33 years old

//Table 1-1. Common printf style format specifiers
-----------------------------------------------------------
Format specifier 	 Description
%c 			 Character
%d			 Decimal number (integer, base 10)
%e			 Exponential floating-point number
%f			 Floating-point number
%i			 Integer (base 10)
%o			 Octal number (base 8)
%s 			 A string of characters
%u			 Unsigned decimal (integer) number
%x			 Hexadecimal number (base 16)
%% 			 Print a “percent” character
\%			 Print a “percent” character
-----------------------------------------------------------

//1.5. Processing a String One Character at a Time
//toUpper 大写 & toLower 小写 & charAt 字符位置
scala> val upper = "hello, world".map(c => c.toUpper)			--->upper: String = HELLO, WORLD
scala> val upper = "hello, world".map(_.toUpper)			--->upper: String = HELLO, WORLD
scala> val upper = "hello, world".filter(_ != 'l').map(_.toUpper)	--->upper: String = HEO, WORD
scala> val result = for {c <- "hello, world";if c != 'l'} yield c.toUpper
scala> val upper = for (c <- "hello, world") yield c.toUpper		--->upper: String = HELLO, WORLD
String s = "Hello";
StringBuilder sb = new StringBuilder();
for (int i = 0; i < s.length(); i++) {char c = s.charAt(i)}
String result = sb.toString();

// first example
"HELLO".map(c => (c.toByte+32).toChar)
// second example
"HELLO".map{ c =>(c.toByte+32).toChar}

scala> def toLower(c: Char): Char = (c.toByte+32).toChar		--->toLower: (c: Char)Char
// use that method with map
scala> "HELLO".map(toLower)						--->res0: String = hello
scala> val s = "HELLO"							--->s: java.lang.String = HELLO
scala> for (c <- s) yield toLower(c)					--->res1: String = hello


object Adler32Checksum {
	val MOD_ADLER = 65521
	def main(args: Array[String]) {
		val sum = adler32sum("Wikipedia")
		printf("checksum (int) = %d\n", sum)
		printf("checksum (hex) = %s\n", sum.toHexString)
	}
	def adler32sum(s: String): Int = {
		var a = 1
		var b = 0
		s.getBytes.foreach{char =>
			a = (char + a) % MOD_ADLER
			b = (b + a) % MOD_ADLER
	}
	b * 65536 + a
	}
}

scala> "hello".getBytes							--->res0: Array[Byte] = Array(104, 101, 108, 108, 111)

//1.6. Finding Patterns in Strings 正则匹配String
scala> val numPattern = "[0-9]+".r					--->numPattern: scala.util.matching.Regex = [0-9]+
scala> val address = "123 Main Street Suite 101"			--->address: java.lang.String = 123 Main Street Suite 101
scala> val match1 = numPattern.findFirstIn(address)			--->match1: Option[String] = Some(123)
scala> val matches = numPattern.findAllIn(address)
							--->matches: scala.util.matching.Regex.MatchIterator = non-empty iterator
scala> matches foreach println				//matches生成的时iterator,所以通过foreach println 输出
	123
	101
//通过import Regex 方法生成
import scala.util.matching.Regex
scala> val matches = numPattern.findAllIn(address).toArray		--->matches: Array[String] = Array(123, 101)
scala> val numPattern = new Regex("[0-9]+")				--->numPattern: scala.util.matching.Regex = [0-9]+
scala> val address = "123 Main Street Suite 101"			--->address: java.lang.String = 123 Main Street Suite 101
scala> val match1 = numPattern.findFirstIn(address)			--->match1: Option[String] = Some(123)
scala> val address = "No address given"					--->address: String = No address given
scala> val match1 = numPattern.findFirstIn(address)			--->match1: Option[String] = None

//使用getOrElse
scala> val address = "123 Main Street Suite 101"
scala> val result = numPattern.findFirstIn(address).getOrElse("no match")		--->result: String = 123
match1 match {
	case Some(s) => println(s"Found: $s")
	case None =>
}
match1.foreach { e =>println(s"Found a match: $e")}


//1.7. Replacing Patterns in Strings 运用正则替换
//call replaceAll on a String:使用replaceAll(pattern,replaceTo)
scala> val address = "123 Main Street".replaceAll("[0-9]", "x")			--->address: java.lang.String = xxx Main Street
//regex.replaceAllIn(String,replaceTo)
scala> val regex = "[0-9]".r							--->regex: scala.util.matching.Regex = [0-9]
scala> val newAddress = regex.replaceAllIn("123 Main Street", "x")		--->newAddress: String = xxx Main Street
//replaceFirst(Regex,replaceTo)
scala> val result = "123".replaceFirst("[0-9]", "x")				--->result: java.lang.String = x23
scala> val regex = "H".r							--->regex: scala.util.matching.Regex = H
scala> val result = regex.replaceFirstIn("Hello world", "J")			--->result: String = Jello world
//pattern实例
scala> val pattern = "([0-9]+) ([A-Za-z]+)".r				--->pattern: scala.util.matching.Regex = ([0-9]+) ([A-Za-z]+)
scala> val pattern(count, fruit) = "100 Bananas"
	count: String = 100
	fruit: String = Bananas


//an Example
"movies near 80301"
"movies 80301"
"80301 movies"
"movie: 80301"
"movies: 80301"
"movies near boulder, co"
"movies near boulder, colorado"

val MoviesZipRE = "movies (\\d{5})".r						// match "movies 80301"
val MoviesNearCityStateRE = "movies near ([a-z]+), ([a-z]{2})".r		// match "movies near boulder, co"

textUserTyped match {
	case MoviesZipRE(zip) => getSearchResults(zip)
	case MoviesNearCityStateRE(city, state) => getSearchResults(city, state)
	case _ => println("did not match a regex")
}

//1.9. Accessing a Character in a String:取出String中字符
scala> "hello".charAt(0)					--->res0: Char = h
scala> "hello"(0)						--->res1: Char = h
scala> "hello"(1)						--->res2: Char = e
scala> "hello"(1)						--->res0: Char = e
scala> "hello".apply(1)						--->res1: Char = e

//1.10. Add Your Own Methods to the String Class:给String class添加自有方法
implicit class StringImprovements(s: String) {def increment = s.map(c => (c + 1).toChar)}
scala> val result = "HAL".increment				--->result: String = IBM
//Put the implicit class in an object
package com.alvinalexander.utils
object StringUtils {implicit class StringImprovements(val s: String) {def increment = s.map(c => (c + 1).toChar)}}
package foo.bar
import com.alvinalexander.utils.StringUtils._
object Main extends App {println("HAL".increment)}

//Put the implicit class in a package object
package com.alvinalexander
package object utils {implicit class StringImprovements(val s: String) {def increment = s.map(c => (c + 1).toChar)}}
package foo.bar
import com.alvinalexander.utils._
object MainDriver extends App {println("HAL".increment)}

//
class StringImprovements(val s: String) {def increment = s.map(c => (c + 1).toChar)}
implicit def stringToString(s: String) = new StringImprovements(s)
"HAL".increment

//Annotate your method return type
implicit class StringImprovements(val s: String) {
	def increment = s.map(c => (c + 1).toChar)
	def decrement = s.map(c => (c - 1).toChar)
	def hideAll = s.replaceAll(".", "*")
}


//Returning other types
implicit class StringImprovements(val s: String) {
	def increment = s.map(c => (c + 1).toChar)
	def decrement = s.map(c => (c - 1).toChar)
	def hideAll: String = s.replaceAll(".", "*")
	def plusOne = s.toInt + 1
	def asBoolean = s match {
		case "0" | "zero" | "" | " " => false
		case _ => true
	}
}

scala> "4".plusOne				--->res0: Int = 5
scala> "0".asBoolean				--->res1: Boolean = false
scala> "1".asBoolean				--->res2: Boolean = true

========================================================CP2 Numbers 数字
Table 2-1. Data ranges of Scala’s built-in numeric types
---------------------------------------------------------------
Data type 		Range
Char 			16-bit unsigned Unicode character
Byte	 		8-bit signed value
Short 			16-bit signed value
Int 			32-bit signed value
Long 			64-bit signed value
Float 			32-bit IEEE 754 single precision float
Double 			64-bit IEEE 754 single precision float
---------------------------------------------------------------
scala> Short.MinValue				--->res0: Short = −32768
scala> Short.MaxValue				--->res1: Short = 32767

//2.1. Parsing a Number from a String
scala> "100".toInt				--->res0: Int = 100
scala> "100".toDouble				--->res1: Double = 100.0
scala> "100".toFloat				--->res2: Float = 100.0
scala> "1".toLong				--->res3: Long = 1
scala> "1".toShort				--->res4: Short = 1
scala> "1".toByte				--->res5: Byte = 1
scala> val b = BigInt("1")			--->b: scala.math.BigInt = 1
scala> val b = BigDecimal("3.14159")		--->b: scala.math.BigDecimal = 3.14159

//Handling a base and radix
scala> Integer.parseInt("1", 2)			--->res0: Int = 1
scala> Integer.parseInt("10", 2)		--->res1: Int = 2
scala> Integer.parseInt("100", 2)		--->res2: Int = 4
scala> Integer.parseInt("1", 8)			--->res3: Int = 1
scala> Integer.parseInt("10", 8)		--->res4: Int = 8
//隐式转换
implicit class StringToInt(s: String) {def toInt(radix: Int) = Integer.parseInt(s, radix)}
scala> "1".toInt(2)				--->res0: Int = 1
scala> "10".toInt(2)				--->res1: Int = 2
scala> "100".toInt(2)				--->res2: Int = 4
scala> "100".toInt(8)				--->res3: Int = 64
scala> "100".toInt(16)				--->res4: Int = 256

//手写toInt
def toInt(s: String):Option[Int] = {
	try {Some(s.toInt)}
	catch {case e: NumberFormatException => None}
}
println(toInt("1").getOrElse(0))
println(toInt("a").getOrElse(0))
val x = toInt(aString).getOrElse(0)
toInt(aString) match {
	case Some(n) => println(n)
	case None => println("Boom! That wasn't a number.")
}
val result = toInt(aString) match {
	case Some(x) => x
	case None => 0 // however you want to handle this
}

//2.2. Converting Between Numeric Types (Casting) 数子转换
scala> val b = a.to[Tab]
 toByte		toChar		toDouble
 toShort	toString	toFloat
 toInt		toLong
scala> 19.45.toInt				--->res0: Int = 19
scala> 19.toFloat				--->res1: Float = 19.0
scala> 19.toDouble				--->res2: Double = 19.0
scala> 19.toLong				--->res3: Long = 19
scala> val a = 1000L				--->a: Long = 1000
scala> a.isValidByte				--->res0: Boolean = false
scala> a.isValidShort				--->res1: Boolean = true

//2.3. Overriding the Default Numeric Type 重写数字类型
scala> val a = 1d				--->a: Double = 1.0
scala> val a = 1f				--->a: Float = 1.0
scala> val a = 1000L				--->a: Long = 1000
scala> val a = 0: Byte				--->a: Byte = 0
scala> val a = 0: Int				--->a: Int = 0
scala> val a = 0: Short				--->a: Short = 0
scala> val a = 0: Double			--->a: Double = 0.0
scala> val a = 0: Float				--->a: Float = 0.0
scala> val a = 0x20				--->a: Int = 32
// if you want to store the value as a Long
scala> val a = 0x20L				--->a: Long = 32
class Foo {
	var a: Short = 0
	var b: Short = _ /* defaults to 0*/
}

//2.4. Replacements for ++ and −−
scala> var a = 1				--->aa: Int = 1
scala> a += 1
scala> println(a)				--->a2
scala> a −= 1
scala> println(a)				--->a1
scala> var i = 1				--->ai: Int = 1
scala> i *= 2
scala> println(i)				--->a2
scala> i *= 2
scala> println(i)				--->a4
scala> i /= 2
scala> println(i)				--->a2
scala> var x = 1d				--->x: Double = 1.0
scala> x += 1
scala> println(x)				--->2.0
scala> var x = 1f				--->x: Float = 1.0
scala> x += 1
scala> println(x)				--->2.0

//2.5. Comparing Floating-Point Numbers
def ~=(x: Double, y: Double, precision: Double) = {if ((x - y).abs < precision) true else false}

scala> val a = 0.3				--->a: Double = 0.3
scala> val b = 0.1 + 0.2			--->b: Double = 0.30000000000000004
scala> ~=(a, b, 0.0001)				--->res0: Boolean = true
scala> ~=(b, a, 0.0001)				--->res1: Boolean = true

object MathUtils {def ~=(x: Double, y: Double, precision: Double) = {if ((x - y).abs < precision) true else false}}
println(MathUtils.~=(a, b, 0.000001))

//2.6. Handling Very Large Numbers (处理大数字)
scala> var b = BigInt(1234567890)		--->b: scala.math.BigInt = 1234567890
scala> var b = BigDecimal(123456.789)		--->b: scala.math.BigDecimal = 123456.789
scala> b + b					--->res0: scala.math.BigInt = 2469135780
scala> b * b					--->res1: scala.math.BigInt = 1524157875019052100
scala> b += 1
scala> println(b)				--->1234567891
scala> b.toInt					--->res2: Int = 1234567891
scala> b.toLong					--->res3: Long = 1234567891
scala> b.toFloat				--->res4: Float = 1.23456794E9
scala> b.toDouble				--->res5: Double = 1.234567891E9
scala> b.isValidByte				--->res6: Boolean = false
scala> b.isValidChar				--->res7: Boolean = false
scala> b.isValidShort				--->res8: Boolean = false
scala> if (b.isValidInt) b.toInt		--->res9: AnyVal = 1234567890
scala> Byte.MaxValue				--->res0: Byte = 127
scala> Short.MaxValue				--->res1: Short = 32767
scala> Int.MaxValue				--->res2: Int = 2147483647
scala> Long.MaxValue				--->res3: Long = 9223372036854775807
scala> Double.PositiveInfinity			--->res0: Double = Infinity
scala> Double.NegativeInfinity			--->res1: Double = -Infinity
scala> 1.7976931348623157E308 > Double.PositiveInfinity			--->res45: Boolean = false

//2.7. Generating Random Numbers (生成随机数)
val r = scala.util.Random
scala> r.nextInt				--->res0: Int = −1323477914
scala> r.nextInt(100)				--->res1: Int = 58

scala> r.nextFloat				--->res2: Float = 0.50317204
// returns a value between 0.0 and 1.0
scala> r.nextDouble				--->res3: Double = 0.6946000981900997
scala> val r = new scala.util.Random(100)	--->r: scala.util.Random = scala.util.Random@bbf4061

//产生随机字母
scala> r.nextPrintableChar			--->res0: Char = H
var range = 0 to r.nextInt(10)
//随机range
scala> var range = 0 to r.nextInt(10)
		--->range: scala.collection.immutable.Range.Inclusive = Range(0, 1, 2, 3)
scala> range = 0 to r.nextInt(10)
		--->range: scala.collection.immutable.Range.Inclusive = Range(0, 1)
scala> for (i <- 0 to r.nextInt(10)) yield i * 2
		--->res1: scala.collection.immutable.IndexedSeq[Int] = Vector(0, 2, 4, 6)
scala> for (i <- 0 to r.nextInt(10)) yield (i * r.nextFloat)
		--->res1: scala.collection.immutable.IndexedSeq[Float] =Vector(0.0, 0.71370363, 1.0783684)
//随机生成字符
scala> for (i <- 0 to r.nextInt(10)) yield r.nextPrintableChar
		--->res4: scala.collection.immutable.IndexedSeq[Char] = Vector(Z, ?, R)
//生成一组5个随机值
val a = for (i <- 1 to 5) yield r.nextInt(100)

//2.8. Creating a Range, List, or Array of Numbers 生成range
for (i <- 1 to 15 by 3) println(i)			--->[1,15] by 3
for (i <- 1 until 5) println(i)				--->[1,5)

val x = (1 to 10).toArray
scala> var range = 0 to scala.util.Random.nextInt(10)
		--->range: scala.collection.immutable.Range.Inclusive = Range(0, 1, 2, 3)
scala> for (i <- 1 to 5) yield i.toDouble
			--->res0: scala.collection.immutable.IndexedSeq[Double] = Vector(1.0, 2.0, 3.0, 4.0, 5.0)

//2.9. Formatting Numbers and Currency 关于数字的格式化
scala> val pi = scala.math.Pi				--->pi: Double = 3.141592653589793
//保留五位小数
scala> println(f"$pi%1.5f")				--->3.14159
scala> f"$pi%1.2f"					--->res1: String = 3.14
scala> f"$pi%06.2f"					--->res2: String = 003.14
scala> "%06.2f".format(pi)				--->res3: String = 003.14

scala> val formatter = java.text.NumberFormat.getIntegerInstance
		--->formatter: java.text.NumberFormat = java.text.DecimalFormat@674dc
scala> formatter.format(10000)				--->res0: String = 10,000
scala> formatter.format(1000000)			--->res1: String = 1,000,000

scala> val locale = new java.util.Locale("de", "DE")		--->locale: java.util.Locale = de_DE
scala> val formatter = java.text.NumberFormat.getIntegerInstance(locale)
		--->formatter: java.text.NumberFormat = java.text.DecimalFormat@674dc
scala> formatter.format(1000000)				--->res2: String = 1.000.000

scala> val formatter = java.text.NumberFormat.getInstance
		--->formatter: java.text.NumberFormat = java.text.DecimalFormat@674dc
scala> formatter.format(10000.33)				--->res0: String = 10,000.33

scala> val formatter = java.text.NumberFormat.getCurrencyInstance
		--->formatter: java.text.NumberFormat = java.text.DecimalFormat@67500
scala> println(formatter.format(123.456789))			--->$123.46
scala> println(formatter.format(1234.56789))			--->$1,234.57
scala> println(formatter.format(12345.6789))			--->$12,345.68
scala> println(formatter.format(123456.789))			--->$123,456.79

scala> import java.util.{Currency, Locale}			--->import java.util.{Currency, Locale}
scala> val de = Currency.getInstance(new Locale("de", "DE"))	--->de: java.util.Currency = EUR
scala> formatter.setCurrency(de)
scala> println(formatter.format(123456.789))			---->EUR123,456.79



========================================================CP3 Control Structures 控制结构
//if else 
val x = if (a) y else z
//for 
for (line <- source.getLines) {
	for{char <- line;if char.isLetter} 
	// char algorithm here ...
}
val nieces = List("emily", "hannah", "mercedes", "porsche")
scala> for (n <- nieces) yield n.capitalize			//首字母大写
		--->res14: List[String] = List(Emily, Hannah, Mercedes, Porsche)

//3.1. Looping with for and foreach (foreach 循环)
val a = Array("apple", "banana", "orange")
//toUpperCase示例
for (i<-a){val s = i.toUpperCase;println(s)}
val newArray = for (e <- a) yield e.toUpperCase
a map(_.toUpperCase) foreach println
val newArray = for (e <- a) yield {val s = e.toUpperCase;s}
				--->newArray: Array[String] = Array(APPLE, BANANA, ORANGE)

for (i <- 0 until a.length) {println(s"$i is ${a(i)}")}
			--->0 is apple
			    1 is banana
			    2 is orange
for ((e, count) <- a.zipWithIndex) {println(s"$count is $e")}
			--->0 is apple
			    1 is banana
			    2 is orange

//for-if (遍历map)
for (i <- 1 to 10 if i < 4) println(i)
//Looping over a Map
val names = Map("fname" -> "Robert","lname" -> "Goren")
for ((k,v) <- names) println(s"key: $k, value: $v")

a.foreach(e => println(e.toUpperCase))
1.to(10).foreach(((i) => println(i)))
1.to(10).withFilter(((i) => i.$percent(2).$eq$eq(0))).foreach(((i) => println(i)))

for {i <- 1 to 10 ; if i != 1 ; if i % 2 == 0} println(i)

//3.2. Using for Loops with Multiple Counters
//创建二维数组 (多维数组)
val array =Array.ofDim[Int](2,2)

//3.3. Using a for Loop with Embedded if Statements (for - if )
for (file <- files) {if (hasSoundFileExtension(file) && !soundFileIsLong(file)) {soundFiles += file}}

for {file <- files;if passesFilter1(file);if passesFilter2(file)} doSomething(file)

//3.4. Creating a for Comprehension (for/yield Combination)
val names = Array("chris", "ed", "maurice")
val capNames = for (e <- names) yield e.capitalize
var fruits = scala.collection.mutable.ArrayBuffer[String]()
fruits += "apple"
fruits += "banana"
fruits += "orange"
val fruits = "apple" :: "banana" :: "orange" :: Nil
val out = for (e <- fruits) yield e.toUpperCase
val out = fruits.map(_.toUpperCase)

//3.5. Implementing break and continue (使用break和continue)
import util.control.Breaks._
object BreakAndContinueDemo extends App {
	println("\n=== BREAK EXAMPLE ===")
	breakable {for (i <- 1 to 10) {println(i);if (i > 4) break}}
	println("\n=== CONTINUE EXAMPLE ===")
	val searchMe = "peter piper picked a peck of pickled peppers"
	var numPs = 0
	for (i <- 0 until searchMe.length) {breakable { if (searchMe.charAt(i) != 'p') {break} else {numPs += 1} }}
	println("Found " + numPs + " p's in the string.")
}

private val breakException = new BreakControl
def break(): Nothing = { throw breakException }
def breakable(op: => Unit) {
	try {op} 
	catch {case ex: BreakControl => if (ex ne breakException) throw ex}
}

//
val searchMe = "peter piper picked a peck of pickled peppers"
var numPs = 0
for (i <- 0 until searchMe.length) {
	breakable {
		if (searchMe.charAt(i) != 'p') {break}
		else {numPs += 1}
	}
}
println("Found " + numPs + " p's in the string.")

//break
//To implement a break, this Scala:
breakable {for (x <- xs) {if (cond)break}}
//corresponds to this Java:
for (X x : xs) {if (cond) break;}
//continue
//To implement continue functionality, this Scala:
for (x <- xs) {breakable {if (cond)break}}
//corresponds to this Java:
for (X x : xs) {if (cond) continue;}

val count = searchMe.count(_ == 'p')


//
package com.alvinalexander.labeledbreaks
object LabeledBreakDemo extends App {
	import scala.util.control._
	val Inner = new Breaks
	val Outer = new Breaks
	Outer.breakable {
		for (i <- 1 to 5) {
			Inner.breakable {
				for (j <- 'a' to 'e') {
					if (i == 1 && j == 'c') Inner.break else println(s"i: $i, j: $j")
					if (i == 2 && j == 'b') Outer.break
				}
			}
		}
	}
}

import scala.util.control._
val Exit = new Breaks
Exit.breakable {for (j <- 'a' to 'e') {if (j == 'c') Exit.break else println(s"j: $j")}}


var barrelIsFull = false
for (monkey <- monkeyCollection if !barrelIsFull) {
	addMonkeyToBarrel(monkey)
	barrelIsFull = checkIfBarrelIsFull
}

def sumToMax(arr: Array[Int], limit: Int): Int = {
	var sum = 0
	for (i <- arr) {sum += i ; if (sum > limit) return limit}
	sum
}
val a = Array.range(0,10)
println(sumToMax(a, 10))


// 实现一个阶层函数 n*(n-1)(n-2)...*1
def factorial(n: Int): Int = {
	if (n == 1) 1
	else n * factorial(n - 1)
}

import scala.annotation.tailrec
def factorial(n: Int): Int = {
	@tailrec 
	def factorialAcc(acc: Int, n: Int): Int = {if (n <= 1) acc ; else factorialAcc(n * acc, n - 1)}
	factorialAcc(1, n)
}


//3.6. Using the if Construct Like a Ternary Operator (使用if)
val absValue = if (a < 0) -a else a
println(if (i == 0) "a" else "b")
hash = hash * prime + (if (name == null) 0 else name.hashCode)


def abs(x: Int) = if (x >= 0) x else -x
def max(a: Int, b: Int) = if (a > b) a else b
val c = if (a > b) a else b


//3.7. Using a Match Expression Like a switch Statement (使用match表达式)
def tes(i:Int)=
i match {
	case 1 => println("January")
	case 2 => println("February")
	case 3 => println("March")
	case 4 => println("April")
	case 5 => println("May")
	case 6 => println("June")
	case 7 => println("July")
	case 8 => println("August")
	case 9 => println("September")
	case 10 => println("October")
	case 11 => println("November")
	case 12 => println("December")
	// catch the default with a variable so you can print it
	case whoa => println("Unexpected case: " + whoa.toString)
}


//使用switch
import scala.annotation.switch
class SwitchDemo {
	val i = 1
	val x = (i: @switch) match {
		case 1 => "One"
		case 2 => "Two"
		case _ => "Other"
	}
}


def getClassAsString(x: Any): String = x match {
	case s: String => s + " is a String"
	case i: Int => "Int"
	case f: Float => "Float"
	case l: List[_] => "List"
	case p: Person => "Person"
	case _ => "Unknown"
}


val monthNumberToName = Map(
	1 -> "January",
	2 -> "February",
	3 -> "March",
	4 -> "April",
	5 -> "May",
	6 -> "June",
	7 -> "July")
val monthName = monthNumberToName(4)
println(monthName) // prints "April"


//3.8. Matching Multiple Conditions with One Case Statement
val i = 5
i match {
	case 1 | 3 | 5 | 7 | 9 => println("odd")
	case 2 | 4 | 6 | 8 | 10 => println("even")
}
val cmd = "stop"
cmd match {
	case "start" | "go" => println("starting")
	case "stop" | "quit" | "exit" => println("stopping")
	case _ => println("doing nothing")
}

trait Command
case object Start extends Command
case object Go extends Command
case object Stop extends Command
case object Whoa extends Command
def executeCommand(cmd: Command) = cmd match {
	case Start | Go => start()
	case Stop | Whoa => stop()
}


//3.9. Assigning the Result of a Match Expression to a Variable
val evenOrOdd = someNumber match {
	case 1 | 3 | 5 | 7 | 9 => println("odd")
	case 2 | 4 | 6 | 8 | 10 => println("even")
}
def isTrue(a: Any) = a match {
	case 0 | "" => false
	case _ => true
}

//3.10. Accessing the Value of the Default Case in a Match Expression(使用default case-default)
i match {
	case 0 => println("1")
	case 1 => println("2")
	case default => println("You gave me: " + default)
}

//3.11. Using Pattern Matching in Match Expressions (正则匹配)
ex:case匹配
def echoWhatYouGaveMe(x: Any): String = x match {
// constant patterns
	case 0 => "zero"
	case true => "true"
	case "hello" => "you said 'hello'"
	case Nil => "an empty List"
// sequence patterns
	case List(0, _, _) => "a three-element list with 0 as the first element"
	case List(1, _*) => "a list beginning with 1, having any number of elements"
	case Vector(1, _*) => "a vector starting with 1, having any number of elements"
// tuples
	case (a, b) => s"got $a and $b"
	case (a, b, c) => s"got $a, $b, and $c"
// constructor patterns
	case Person(first, "Alexander") => s"found an Alexander, first name = $first"
	case Dog("Suka") => "found a dog named Suka"
// typed patterns
	case s: String => s"you gave me this string: $s"
	case i: Int => s"thanks for the int: $i"
	case f: Float => s"thanks for the float: $f"
	case a: Array[Int] => s"an array of int: ${a.mkString(",")}"
	case as: Array[String] => s"an array of strings: ${as.mkString(",")}"
	case d: Dog => s"dog: ${d.name}"
	case list: List[_] => s"thanks for the List: $list"
	case m: Map[_, _] => m.toString
// the default wildcard pattern
	case _ => "Unknown"
}


object LargeMatchTest extends App {
	case class Person(firstName: String, lastName: String)
	case class Dog(name: String)
// trigger the constant patterns
	println(echoWhatYouGaveMe(0))
	println(echoWhatYouGaveMe(true))
	println(echoWhatYouGaveMe("hello"))
	println(echoWhatYouGaveMe(Nil))
// trigger the sequence patterns
	println(echoWhatYouGaveMe(List(0,1,2)))
	println(echoWhatYouGaveMe(List(1,2)))
	println(echoWhatYouGaveMe(List(1,2,3)))
	println(echoWhatYouGaveMe(Vector(1,2,3)))
// trigger the tuple patterns
	println(echoWhatYouGaveMe((1,2)))
	println(echoWhatYouGaveMe((1,2,3)))
// two element tuple
// three element tuple
// trigger the constructor patterns
	println(echoWhatYouGaveMe(Person("Melissa", "Alexander")))
	println(echoWhatYouGaveMe(Dog("Suka")))
// trigger the typed patterns
	println(echoWhatYouGaveMe("Hello, world"))
	println(echoWhatYouGaveMe(42))
	println(echoWhatYouGaveMe(42F))
	println(echoWhatYouGaveMe(Array(1,2,3)))
	println(echoWhatYouGaveMe(Array("coffee", "apple pie")))
	println(echoWhatYouGaveMe(Dog("Fido")))
	println(echoWhatYouGaveMe(List("apple", "banana")))
	println(echoWhatYouGaveMe(Map(1->"Al", 2->"Alexander")))
// trigger the wildcard pattern
	println(echoWhatYouGaveMe("33d"))
}


case list: List[_] => s"thanks for the List: $list"
case m: Map[_, _] => m.toString
case m: Map[a, b] => m.toString
case list: List[x] => s"thanks for the List: $list"

import java.io.File
sealed trait RandomThing
case class RandomFile(f: File) extends RandomThing
case class RandomString(s: String) extends RandomThing
class RandomNoiseMaker {
	def makeRandomNoise(t: RandomThing) = t match {
		case RandomFile(f) => playSoundFile(f)
		case RandomString(s) => speak(s)
	}
}


case class Person(firstName: String, lastName: String)
object Test2 extends App {
	def matchType(x: Any): String = x match {
//case x: List(1, _*) => s"$x" // doesn't compile
	case x @ List(1, _*) => s"$x"
// works; prints the list
//case Some(_) => "got a Some" // works, but can't access the Some
//case Some(x) => s"$x" // works, returns "foo"
	case x @ Some(_) => s"$x"
// works, returns "Some(foo)"
	case p @ Person(first, "Doe") => s"$p"
// works, returns "Person(John,Doe)"
	}
	println(matchType(List(1,2,3)))
	println(matchType(Some("foo")))
	println(matchType(Person("John", "Doe")))
// prints "List(1, 2, 3)"
// prints "Some(foo)"
// prints "Person(John,Doe)"
}


//Using Some and None in match expressions (match-Option)
def toInt(s: String): Option[Int] = {
	try {Some(Integer.parseInt(s.trim))}
	catch {case e: Exception => None}
}

toInt("42") match {
	case Some(i) => println(i)
	case None => println("That wasn't an Int.")
}


//3.12. Using Case Classes in Match Expressions 
trait Animal
case class Dog(name: String) extends Animal
case class Cat(name: String) extends Animal
case object Woodpecker extends Animal
object CaseClassTest extends App {
	def determineType(x: Animal): String = x match {
		case Dog(moniker) => "Got a Dog, name = " + moniker
		case _:Cat => "Got a Cat (ignoring the name)"
		case Woodpecker => "That was a Woodpecker"
		case _ => "That was something else"
	}
	println(determineType(new Dog("Rocky")))
	println(determineType(new Cat("Rusty the Cat")))
	println(determineType(Woodpecker))
}

//3.13. Adding if Expressions (Guards) to Case Statements  (case-if)

i match {
	case a if 0 to 9 contains a => println("0-9 range: " + a)
	case b if 10 to 19 contains b => println("10-19 range: " + b)
	case c if 20 to 29 contains c => println("20-29 range: " + c)
	case _ => println("Hmmm...")
}

//Use it to match different values of an object:
num match {
	case x if x == 1 => println("one, a lonely number")
	case x if (x == 2 || x == 3) => println(x)
	case _ => println("some other value")
}

stock match{
	case x if (x.symbol == "XYZ" && x.price < 20) => buy(x)
	case x if (x.symbol == "XYZ" && x.price > 50) => sell(x)
	case _ => // do nothing
}
scala> case class Person(name:String,age:Int)			--->defined class Person
scala> val j=new Person("jack",11)				--->j: Person = Person(jack,11)
scala> val z=new Person("zieox",22)				--->z: Person = Person(zieox,22)
def speak(p: Person) = p match{
	case Person(name,_) if name == "zieox" => println("Yubba dubba doo")
	case Person(name,_) if name == "Bam Bam" => println("Bam bam!")
	case _ => println("Watch the Flintstones!")
}
scala> speak(j)			--->Watch the Flintstones!
scala> speak(z)			--->Yubba dubba doo




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值