0
0
0
1. 云栖社区>
2. 博客>
3. 正文

经过了一段时间的泛函编程讨论，始终没能实实在在的明确到底泛函编程有什么区别和特点；我是指在现实编程的情况下所谓的泛函编程到底如何特别。我们已经习惯了传统的行令式编程（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 => Int
2   def lengthOf(s: String): Int = s.length         //> lengthOf: (s: String)Int
3   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] = <functio
5                                                   //| 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] = <function1
3                                                   //| >
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: A
3   }
4   object Box {
5       def apply[A](a: A) = new Box[A] {
6           def get = a
7       }
8   }``````

``````1   val bxHello = Box("Hello")                      //> bxHello  : ch12.ex4.Box[String] = ch12.ex4\$Box\$\$anon\$1@3581c5f3
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] = ch12.ex4\$Box\$\$anon\$1@3581c5f3
11   bxHello map {_.length}                          //> res0: ch12.ex4.Box[Int] = ch12.ex4\$Box\$\$anon\$1@340f438e
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 = a
10       }
11   }
12   val bxHello = Box("Hello")                      //> bxHello  : ch12.ex4.Box[String] = ch12.ex4\$Box\$\$anon\$1@3581c5f3
13   bxHello map {_.length}                          //> res0: ch12.ex4.Box[Int] = ch12.ex4\$Box\$\$anon\$1@340f438e
14   (bxHello map {a => a.length}).get               //> res1: Int = 5
15
16   bxHello flatMap {a => Box(a.length)}            //> res2: ch12.ex4.Box[Int] = ch12.ex4\$Box\$\$anon\$1@30c7da1e
17   (bxHello flatMap {a => Box(a.length)}).get      //> res3: Int = 5
18
19   def lengthOf(s: String): Int = s.length         //> lengthOf: (s: String)Int
20   bxHello apply {Box(lengthOf _)}                 //> res4: ch12.ex4.Box[Int] = ch12.ex4\$Box\$\$anon\$1@5b464ce8
21   (bxHello apply {Box(lengthOf _)}).get           //> res5: Int = 5``````

``````1   val word = for {
2       x <- Box("Hello")
3       y = x.length
4       z <- Box(" World!")
5       w = x + z
6   } yield w                                       //> word  : ch12.ex4.Box[String] = ch12.ex4\$Box\$\$anon\$1@2d554825
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]
16
17   val bxHello = Box("Hello")                      //> bxHello  : ch12.ex5.Box[String] = ch12.ex5\$Box\$\$anon\$1@511baa65
18   bxHello map {_.length}                          //> res0: ch12.ex5.Box[Int] = ch12.ex5\$Box\$\$anon\$1@340f438e
19   (bxHello map {a => a.length}).get               //> res1: Int = 5
20
21   bxHello flatMap {a => Box(a.length)}            //> res2: ch12.ex5.Box[Int] = ch12.ex5\$Box\$\$anon\$1@30c7da1e
22   (bxHello flatMap {a => Box(a.length)}).get      //> res3: Int = 5
23
24   def lengthOf(s: String): Int = s.length         //> lengthOf: (s: String)Int
25   bxHello apply {Box(lengthOf _)}                 //> res4: ch12.ex5.Box[Int] = ch12.ex5\$Box\$\$anon\$1@5b464ce8
26   (bxHello apply {Box(lengthOf _)}).get           //> res5: Int = 5
27
28   val word = for {
29       x <- Box("Hello")
30       y = x.length
31       z <- Box(" World!")
32       w = x + z
33   } yield w                                       //> word  : ch12.ex5.Box[String] = ch12.ex5\$Box\$\$anon\$1@2d554825
34   word.get                                        //> res6: String = Hello World!``````

+ 关注

corcosa 12833人浏览