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时才施用通过壳提供的操作函数。

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 => 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) }}}

2 //> chainABC : Exercises.monad.Bag[Int] = [email protected]

3 chainABC.content //> res0: Int = 12

4

5 val bagABC = Bag(3) >>= {a => Bag(4) >>= {b => Bag(5) map {c => (a+b+c) }}}

6 //> bagABC : Exercises.monad.Bag[Int] = [email protected]

7 bagABC.content //> res1: Int = 12

8 val bagHello = Bag("Hello") >>= {a => Bag(" John,") >>= {b => Bag("how are you?") map {c => (a+b+c) }}}

9 //> bagHello : Exercises.monad.Bag[String] = [email protected]

10 //| 09

11 bagHello.content //> res2: String = Hello John,how are you?

现在我们可以使用最希望用的for-comprehension来实现上面的行令编程了：

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 ?")

13 } yield ( a+b+c) //> concatABC : Exercises.monad.Bag[String] = [email protected]

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

Top