## 动力学知识库

经过了一段时间的泛函编程讨论，始终没能实实在在的明确到底泛函编程有什么区别和特点；我是指在现实编程的情况下所谓的泛函编程到底如何特别。我们已经习惯了传统的行令式编程（imperative programming），总是先入为主的认为软件编程就是一行接着一行的更改某些变量状态指令：明刀明枪，字里行间目的和方式都很明确。我们就以一步步更改程序状态的方式，一行一行的拼凑指令：这就是典型的行令式编程了。

A => B      >>> F[A] => F[B]

A => F[B]   >>> F[A] => F[B]

F[A => B]   >>> F[A] => F[B]

case class Box[A](a: A)  >>> 这是一个带嵌入变量的泛函类型

1、 A => B

`1 case class Box[A](a: A)2 def map[A,B](f: A => B): Box[A] => Box[B] = {3 (ba: Box[A]) => Box(f(ba.a))4 } //> map: [A, B](f: A => B)ch12.ex3.Box[A] => ch12.ex3.Box[B]`

`1 //f: String => Int2 def lengthOf(s: String): Int = s.length //> lengthOf: (s: String)Int3 val funcMapTransform = map(lengthOf) //> funcMapTransform : ch12.ex3.Box[String] => ch12.ex3.Box[Int] = <function1>4 funcMapTransform(Box("Hello World!")) //> res0: ch12.ex3.Box[Int] = Box(12)`

2、A => F[B]

`1 case class Box[A](a: A)2 def flatMap[A,B](f: A => Box[B]): Box[A] => Box[B] = {3 (ba: Box[A]) => f(ba.a)4 }`

`1 //f: String => Box[Int]2 def boxedLengthOf(s: String) = Box(s.length) //> boxedLengthOf: (s: String)ch12.ex3.Box[Int]3 val funcFlatMapTransform = flatMap(boxedLengthOf)4 //> funcFlatMapTransform : ch12.ex3.Box[String] => ch12.ex3.Box[Int] = <functio5 //| n1>6 funcFlatMapTransform(Box("Hello World!")) //> res1: ch12.ex3.Box[Int] = Box(12)`

3、Box[A => B]

`1 case class Box[A](a: A)2 def apply[A,B](f: Box[A => B]): Box[A] => Box[B] = {3 (ba: Box[A]) => Box(f.a(ba.a))4 }`

`1 //f: Box[String => Int]2 val funcApplyTransform = apply(Box(lengthOf _))//> funcApplyTransform : ch12.ex3.Box[String] => ch12.ex3.Box[Int] = <function13 //| >4 funcApplyTransform(Box("Hello World!")) //> res2: ch12.ex3.Box[Int] = Box(12)`

apply函数就是Applicative函数

(A => B) => (F[A] => F[B])

(A => B) => F[A] => F[B]

uncurry ((A => B), F[A]) => F[B]

map(F[A])(A => B): F[B]

flatMap(F[A])(A => F[B]): F[B]

apply(F[A])(F[A => B]): F[B]

`1  trait Box[A] {2  def get: A3  }4  object Box {5 def apply[A](a: A) = new Box[A] {6 def get = a7  }8 }`

`1 val bxHello = Box("Hello") //> bxHello : ch12.ex4.Box[String] = [email protected]2 bxHello.get //> res0: String = Hello`

` 1  trait Box[A] { 2  def get: A 3 def map[B](f: A => B): Box[B] = Box(f(get)) 4  } 5  object Box { 6 def apply[A](a: A) = new Box[A] { 7 def get = a 8  } 9  }10 val bxHello = Box("Hello") //> bxHello : ch12.ex4.Box[String] = [email protected]11 bxHello map {_.length} //> res0: ch12.ex4.Box[Int] = [email protected]12 (bxHello map {a => a.length}).get //> res1: Int = 5`

` 1  trait Box[A] { 2  def get: A 3 def map[B](f: A => B): Box[B] = Box(f(get)) 4 def flatMap[B](f: A => Box[B]): Box[B] = f(get) 5 def apply[B](f: Box[A => B]): Box[B] = Box(f.get(get)) 6  } 7  object Box { 8 def apply[A](a: A) = new Box[A] { 9 def get = a10  }11  }12 val bxHello = Box("Hello") //> bxHello : ch12.ex4.Box[String] = [email protected]13 bxHello map {_.length} //> res0: ch12.ex4.Box[Int] = [email protected]14 (bxHello map {a => a.length}).get //> res1: Int = 51516 bxHello flatMap {a => Box(a.length)} //> res2: ch12.ex4.Box[Int] = [email protected]17 (bxHello flatMap {a => Box(a.length)}).get //> res3: Int = 51819 def lengthOf(s: String): Int = s.length //> lengthOf: (s: String)Int20 bxHello apply {Box(lengthOf _)} //> res4: ch12.ex4.Box[Int] = [email protected]21 (bxHello apply {Box(lengthOf _)}).get //> res5: Int = 5`

`1 val word = for {2 x <- Box("Hello")3 y = x.length4 z <- Box(" World!")5 w = x + z6 } yield w //> word : ch12.ex4.Box[String] = [email protected]7 word.get //> res6: String = Hello World!`

` 1  trait Box[A] { 2  def get: A 3  } 4  object Box { 5 def apply[A](a: A) = new Box[A] { 6 def get = a 7  } 8  } 9 class BoxOps[A](ba: Box[A]) {10 def map[B](f: A => B): Box[B] = Box(f(ba.get))11 def flatMap[B](f: A => Box[B]): Box[B] = f(ba.get)12 def apply[B](f: Box[A => B]): Box[B] = Box(f.get(ba.get))13  }14 implicit def toBoxOps[A](ba: Box[A]) = new BoxOps(ba)15 //> toBoxOps: [A](ba: ch12.ex5.Box[A])ch12.ex5.BoxOps[A]1617 val bxHello = Box("Hello") //> bxHello : ch12.ex5.Box[String] = [email protected]18 bxHello map {_.length} //> res0: ch12.ex5.Box[Int] = [email protected]19 (bxHello map {a => a.length}).get //> res1: Int = 52021 bxHello flatMap {a => Box(a.length)} //> res2: ch12.ex5.Box[Int] = [email protected]22 (bxHello flatMap {a => Box(a.length)}).get //> res3: Int = 52324 def lengthOf(s: String): Int = s.length //> lengthOf: (s: String)Int25 bxHello apply {Box(lengthOf _)} //> res4: ch12.ex5.Box[Int] = [email protected]26 (bxHello apply {Box(lengthOf _)}).get //> res5: Int = 52728 val word = for {29 x <- Box("Hello")30 y = x.length31 z <- Box(" World!")32 w = x + z33 } yield w //> word : ch12.ex5.Box[String] = [email protected]34 word.get //> res6: String = Hello World!`