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

``````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))

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

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 ｝``````

``````rait Bag[A] {
def content: A
}
object Bag {
def apply[A](a: A) = new Bag[A] { def content = a }
def point[A](a: => A) = Bag(a)
def bind[A,B](ba: Bag[A])(f: A => Bag[B]): Bag[B] = f(ba.content)
}
}``````

``````val chainABC = Bag(3) flatMap {a => Bag(4) flatMap {b => Bag(5) flatMap  {c => Bag(a+b+c) }}}
chainABC.content                                  //> res0: Int = 12

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

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

``````val addABC: Bag[Int] = for {
a <- Bag(3)
b <- Bag(4)
c <- Bag(5)
addABC.content                                    //> res2: Int = 12

val concatABC: Bag[String] =
for {
a <- Bag("hello")
b <- Bag(" jonh,")
c <- Bag("how are you ?")
//| 772
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]``````

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

object Bag {
def point[A](a: => A) = Bagged(a)
def bind[A,B](ba: Bag[A])(f: A => Bag[B]): Bag[B] = ba match {
case Bagged(a) => f(a)
case _ => Emptied
}
}
}``````

``````val chainABC = Monad[Bag].point(3) flatMap {a => Monad[Bag].point(4) flatMap {b => Monad[Bag].point(5) flatMap  {c => Bagged(a+b+c) }}}
//> chainABC  : Exercises.monad.Bag[Int] = Bagged(12)
val bagABC = Monad[Bag].point(3) >>= {a => Monad[Bag].point(4) >>= {b => Monad[Bag].point(5) map {c => (a+b+c) }}}
//> bagABC  : Exercises.monad.Bag[Int] = Bagged(12)
val bagHello = Monad[Bag].point("Hello") >>= {a => Monad[Bag].point(" John,") >>= {b => Monad[Bag].point("how are you?") map {c => (a+b+c) }}}
//> bagHello  : Exercises.monad.Bag[String] = Bagged(Hello John,how are you?)
val addABC: Bag[Int] = for {

val concatABC: Bag[String] =
for {
c <- Monad[Bag].point("how are you ?")
} yield ( a+b+c)                                  //> concatABC  : Exercises.monad.Bag[String] = Bagged(hello jonh,how are you ?)
//|``````

``````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])

``````val addABC: Bag[Int] = for {
x <- (Emptied: Bag[Int])

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

+ 关注

corcosa 15815人浏览