```1 // Functor    :  map[T,U]    (F[T])(f:   T => U):  F[U]
2 // Applicative:  ap[T,U]     (F[T])(f: F[T => U]): F[U]
3 // Monad      :  flatMap[T,U](F[T])(f: T => F[U]): F[U]```

```1 mplicit object optionFunctor extends Functor[Option] {
2     def map[T,U](ot: Option[T])(f: T => U): Option[U] = ot match {
3         case Some(t) => Some(f(t))
4         case None => None
5     }
6 }```

Option Functor实例驱动函数map的意思是说如果目标类型F[T]的值是个Some，那么我们就在Some壳内施用参数提供的一般函数f；如果目标值是None就不施用函数。我们再看看List Functor：

```1 implicit object listFunctor extends Functor[List] {
2     def map[T,U](lt: List[T])(f: T => U): List[U] = lt match {
3         case Nil => Nil
5     }
6 }```

List Functor的map函数彰显出对一串在壳内元素逐个转变的特性。从List操作方式就很容易理解：list.map(t => transform(t))

```1 implicit object objectApplicative extends Applicative[Option] {
2     def point[T](t: T): Option[T] = Some(t)
3     def ap[T,U](ot: Option[T])(of: Option[T => U]): Option[U] = (ot, of) match {
4         case (Some(t), Some(f)) => Some(f(t))
5         case _ => None
6     }
7 }```

Option Applicative的驱动函数ap又一次凸显了Option的特别处理方式：只有在目标值和操作函数都不为None时才施用通过壳提供的操作函数。

```1 mplicit object optionMonad extends Monad[Option] {
2     def flatMap[T,U](ot: Option[T])(f: T => Option[U]): Option[U] = ot match {
3         case Some(t) => f(t)
4         case _ => None
5     }
6 }```

F[A](a => F[B](b => F[C](c => F[D])...))。用flatMap链表示：

`1  fa.flatMap(a => fb.flatMap(b => fc.flatMap(c => fd.map(...))))`

```1 //   for {
2 //      a <- (fa: F[A])
3 //      b <- (fb: F[A])
4 //      c <- (fc: F[A])
5 //   } yield { ... }```

```1 ef map[A,B](fa: F[A])(f: A => B): F[B] =
2   fa flatMap {a => point(f(a))}
3 def ap[A,B](fa: F[A])(ff: F[A => B]): F[B] =
4   ff flatMap { f => fa flatMap {a => point(f(a)) }}```

```1 var a = 3
2 var b = 4
3 var c = a + b```

```1 trait Bag[A] {
2     def content: A
3 }
4 object Bag {
5     def apply[A](a: A) = new Bag[A] { def content = a }
6 ｝```

``` 1 rait Bag[A] {
2     def content: A
3 }
4 object Bag {
5     def apply[A](a: A) = new Bag[A] { def content = a }
7         def point[A](a: => A) = Bag(a)
8         def bind[A,B](ba: Bag[A])(f: A => Bag[B]): Bag[B] = f(ba.content)
9     }
10 }```

``` 1 val chainABC = Bag(3) flatMap {a => Bag(4) flatMap {b => Bag(5) flatMap  {c => Bag(a+b+c) }}}
3 chainABC.content                                  //> res0: Int = 12
4
5 val bagABC = Bag(3) >>= {a => Bag(4) >>= {b => Bag(5) map {c => (a+b+c) }}}
7 bagABC.content                                    //> res1: Int = 12
8 val bagHello = Bag("Hello") >>= {a => Bag(" John,") >>= {b => Bag("how are you?") map {c => (a+b+c) }}}
10                                                   //| 09
11 bagHello.content                                  //> res2: String = Hello John,how are you?```

``` 1 val addABC: Bag[Int] = for {
2   a <- Bag(3)
3   b <- Bag(4)
4   c <- Bag(5)
6 addABC.content                                    //> res2: Int = 12
7
8 val concatABC: Bag[String] =
9 for {
10   a <- Bag("hello")
11   b <- Bag(" jonh,")
12   c <- Bag("how are you ?")
14                                                   //| 772
15 concatABC.content                                 //> res3: String = hello jonh,how are you ?```

```1 trait Bag[+A] {}
2 case class Bagged[+A](content: A) extends Bag[A]
3 case object Emptied extends Bag[Nothing]```

``` 1 trait Bag[+A] {}
2 case class Bagged[+A](content: A) extends Bag[A]
3 case object Emptied extends Bag[Nothing]
4
5 object Bag {
7         def point[A](a: => A) = Bagged(a)
8         def bind[A,B](ba: Bag[A])(f: A => Bag[B]): Bag[B] = ba match {
9           case Bagged(a) => f(a)
10           case _ => Emptied
11         }
12     }
13 }```

``` 1 val chainABC = Monad[Bag].point(3) flatMap {a => Monad[Bag].point(4) flatMap {b => Monad[Bag].point(5) flatMap  {c => Bagged(a+b+c) }}}
2                                                   //> chainABC  : Exercises.monad.Bag[Int] = Bagged(12)
3 val bagABC = Monad[Bag].point(3) >>= {a => Monad[Bag].point(4) >>= {b => Monad[Bag].point(5) map {c => (a+b+c) }}}
4                                                   //> bagABC  : Exercises.monad.Bag[Int] = Bagged(12)
5 val bagHello = Monad[Bag].point("Hello") >>= {a => Monad[Bag].point(" John,") >>= {b => Monad[Bag].point("how are you?") map {c => (a+b+c) }}}
6                                                   //> bagHello  : Exercises.monad.Bag[String] = Bagged(Hello John,how are you?)
7 val addABC: Bag[Int] = for {
12
13 val concatABC: Bag[String] =
14 for {
17   c <- Monad[Bag].point("how are you ?")
18 } yield ( a+b+c)                                  //> concatABC  : Exercises.monad.Bag[String] = Bagged(hello jonh,how are you ?)
19                                                   //| ```

```1 val bagABC = Monad[Bag].point(3) >>= {a => (Bagged(4): Bag[Int]) >>= {b => Monad[Bag].point(5) >>= { c => (Emptied: Bag[Int]) map {c => (a+b+c) }}}}
2                                                   //> bagABC  : Exercises.monad.Bag[Int] = Emptied```

flatMap链条中间出现了Emptied，运算终断，返回Emptied结果。注意下面的表达形式：

(Bagged(3): Bag[Int])

``` 1 val addABC: Bag[Int] = for {
3   x <- (Emptied: Bag[Int])
7
8 val concatABC: Bag[String] =
9 for {
11   x <- (Emptied: Bag[Int])
13   c <- Monad[Bag].point("how are you ?")
14 } yield ( a+b+c)                                  //> concatABC  : Exercises.monad.Bag[String] = Emptied```

0 条评论

## 相关文章

3777

### 《Kotin 极简教程》第8章 函数式编程（FP）(1)第8章 函数式编程（FP）《Kotlin极简教程》正式上架：

"函数式编程", 又称泛函编程, 是一种"编程范式"（programming paradigm），也就是如何编写程序的方法论。它的基础是 λ 演算（lambda...

982

### （原创）详解KMP算法

KMP算法应该是每一本《数据结构》书都会讲的，算是知名度最高的算法之一了，但很可惜，我大二那年压根就没看懂过~~~ 之后也在很多地方也都经常看到讲解KMP算法的...

2217

### 2017"百度之星"程序设计大赛 - 复赛1001&&HDU 6144 Arithmetic of Bomb【java大模拟】

Arithmetic of Bomb Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768...

3087

1072

### MapReduce设计模式

MapReduce设计模式(MapReduce Design Pattern) 整个MapReduce作业的阶段主要可以分为以下四种： 　　1、Input-M...

3196

3647

1282

2914

3656