``` 1   trait Monad[M[_]] {
2       def unit[A](a: A): M[A]
3       def flatMap[A,B](ma: M[A])(f: A => M[B]): M[B]
4       def compose[A,B,C](f: A => M[B], g: B => M[C]): A => M[C] = {
5           a => { flatMap(f(a))(g)}
6       }
7       def flatMapByCompose[A,B](ma: M[A])(f: A => M[B]): M[B] = {
8           compose(((_):Unit) => ma,f)(())
9       }
10       def join[A](mma: M[M[A]]): M[A] = {
11           flatMap(mma)(ma => ma)
12       }
13       def map[A,B](ma: M[A])(f: A => B): M[B] = {
14           flatMap(ma)(a => unit(f(a)))
15       }
16       def flatMapByJoin[A,B](ma: M[A])(f: A => M[B]): M[B] = {
17           join(map(ma)(a => f(a)))
18       }
19       def composeByJoin[A,B,C](f: A => M[B], g: B => M[C]): A => M[C] = {
20           a => { join(map(f(a))(g)) }
21       }
22   }```

```1   trait Functor[F[_]] {
2       def map[A,B](fa: F[A])(f: A => B): F[B]
3   }
4   trait Monad[M[_]] extends Functor[M]{
5       def unit[A](a: A): M[A]
6       def flatMap[A,B](ma: M[A])(f: A => M[B]): M[B]
7       def map[A,B](ma: M[A])(f: A => B): M[B] = {
8           flatMap(ma)(a => unit(f(a)))
9       }```

```1       def map2[A,B,C](ma: M[A], mb: M[B])(f: (A,B) => C): M[C] = {
2           flatMap(ma)(a => map(mb)(b => f(a,b)))
3       }```

```1       def sequence[A](lma: List[M[A]]): M[List[A]] = {
2           lma.foldRight(unit(List[A]()))((a,ma) => map2(a,ma)(_ :: _))
3       }
4       def traverse[A,B](la: List[A])(f: A => M[B]): M[List[B]] = {
5           la.foldRight(unit(List[B]()))((a,mb) => map2(f(a),mb)(_ :: _))
6       }```

```1  def Map2[A,B,C](ma: Option[A], mb: Option[B])(f: (A,B) => C): Option[C] = {
2       (ma,mb) match {
3           case (Some(a),Some(b)) => Some(f(a,b))
4           case _ => None
5       }
6   }```

```1   def map[A,B]      (ma: M[A])       (f: A => B)    : M[B]
2   def map2[A,B,C](ma: M[A], mb: M[B])(f: (A,B) => C): M[C]
3   def flatMap[A,B]  (ma: M[A])       (f: A => M[B]) : M[B]```

map和map2都是正宗的在高阶数据类型结构内的函数施用，但flatMap的函数是 A=>M[B]，会破坏结果的结构。例如：我们对一个有3个元素的List进行map操作，结果仍然是一个3个元素的List。但如果flatMap的话就可能会产生不同长度的List：

`1 def apply[A,B](fab: F[A => B])(fa: F[A]): F[B]`

``` 1   trait Applicative[F[_]] extends Functor[F] {
2       def unit[A](a: A): F[A]
3       def map2[A,B,C](fa: F[A], fb: F[B])(f: (A,B) => C): F[C] = {
4           apply(fb)(map(fa)(f.curried))     //map(fa)(a => (b => c)) >>> F[A=>B]
5       }
6       def apply[A,B](fa: F[A])(fab: F[A =>B]): F[B] = {
7  //         map2(fab,fa)((f,a) => f(a))
8             map2(fab,fa)(_(_))
9       }
10       def map[A,B](fa: F[A])(f: A => B): F[B] = {
11  //         map2(unit(f),fa)((f,a) => f(a))
12           map2(unit(f),fa)(_(_))
13       }
14       def mapByApply[A,B](fa: F[A])(f: A => B): F[B] = {
15           apply(fa)(unit(f))
16       }
17   }```

``` 1 def Map2[A,B,C](ma: Option[A], mb: Option[B])(f: (A,B) => C): Option[C] = {
2       (ma,mb) match {
3           case (Some(a),Some(b)) => Some(f(a,b))
4           case _ => None
5       }
6   }
7   def apply[A,B](ma: Option[A])(f: Option[A => B]): Option[B] = {
8       (ma,f) match {
9           case (Some(a),Some(f)) => Some(f(a))
10           case _ => None
11       }
12   }
13   def flatMap[A,B](ma: Option[A])(f: A => Option[B]): Option[B] = {
14       ma match {
15           case Some(a) => f(a)
16           case _ => None
17       }
18   }```

``` 1     def map3[A,B,C,D](ma: M[A], mb: M[B], mc: M[C])(f: (A,B,C) => D): M[D] = {
2         map2(ma,
3           map2(mb,mc){(b,c) => (b,c)}
4           ){(a,bc) => {
5            val (b,c) = bc
6              f(a,b,c)
7           }}
8     }
9     def map4[A,B,C,D,E](ma: M[A], mb: M[B], mc: M[C], md: M[D])(f: (A,B,C,D) => E): M[E] = {
10         map2(ma,
11           map2(mb,
12           map2(mc,md){(c,d) => (c,d)}
13           ){(b,cd) => (b,cd)}
14           ){(a,bcd) => {
15               val (b,(c,d)) = bcd
16               f(a,b,c,d)
17           }}
18     }
19     def map5[A,B,C,D,E,F](ma: M[A], mb: M[B], mc: M[C], md: M[D], me: M[E])(f: (A,B,C,D,E) => F): M[F] = {
20         map2(ma,
21           map2(mb,
22           map2(mc,
23           map2(md,me){(d,e) => (d,e)}
24           ){(c,de) => (c,de)}
25           ){(b,cde) => (b,cde)}
26           ){(a,bcde) => {
27               val (b,(c,(d,e))) = bcde
28               f(a,b,c,d,e)
29           }}
30     }```

unit(f.curried) = M[A=>B=>C]。apply(M[A])(M[A=>B]):M[B]。我们可以针对每个M值分步施用apply：A=>B=>C >>> A=>BC >>> BC=B=>C,apply(M[A])(unit(f.curried))=M[B=>C],那么可以用apply来实现map3,map4,map5:

``` 1       def map3[A,B,C,D](ma: F[A], mb: F[B], mc: F[C])(f: (A,B,C) => D): F[D] = {
2           apply(mc)(apply(mb)
3               (apply(ma)(unit(f.curried))))
4       }
5       def map4[A,B,C,D,E](ma: F[A], mb: F[B], mc: F[C],md: F[D])(f: (A,B,C,D) => E): F[E] = {
6           apply(md)(apply(mc)
7           (apply(mb)
8           (apply(ma)(unit(f.curried)))))
9       }
10       def map5[A,B,C,D,E,G](ma: F[A], mb: F[B], mc: F[C],md: F[D], me: F[E])(f: (A,B,C,D,E) => G): F[G] = {
11           apply(me)(apply(md)
12           (apply(mc)
13           (apply(mb)
14           (apply(ma)(unit(f.curried))))))
15       }```

``` 1  trait Monad[M[_]] extends Applicative[M]{
2       def unit[A](a: A): M[A]
3       def flatMap[A,B](ma: M[A])(f: A => M[B]): M[B] = {
4           join(map(ma)(f))
5       }
6       def compose[A,B,C](f: A => M[B], g: B => M[C]): A => M[C] = {
7           a => { flatMap(f(a))(g)}
8       }
9       def join[A](mma: M[M[A]]): M[A] = {
10           flatMap(mma)(ma => ma)
11       }
12        override def apply[A,B](ma: M[A])(fab: M[A => B]): M[B] = {
13           flatMap(fab)(f => flatMap(ma)(a => unit(f(a))))
14       }     ```

``` 1  implicit def eitherMonad[E] = new Monad[({type l[V] = Either[E,V]})#l] {
2       def unit[A](a: A) = Right(a)
3       def flatMap[A,B](ea: Either[E,A])(f: A => Either[E,B]): Either[E,B] = {
4           ea match {
5               case Right(a) => f(a)
6               case Left(e) => Left(e)
7           }
8       }
9   }
10   def validateName(name: String): Either[String,String]
11   def validatebirthdate(birthdate: Date): Either[String,Date]
12   def validatePhone(phone: String): Either[String,String]```

```1 validateName(field1) flatMap (f1 =>
2 validateBirthdate(field2) flatMap (f2 =>
3 validatePhone(field3) map (WebForm(_, _, _))```

WebForm是个构建函数（constructor）: case class WebForm(name: String, birthdate: Date, phone: String)。如果我们像上面那样逐个flatMap验证函数结果的话，从flatMap的具体实现代码可以看出：如果validName返回错误的话，下面的validateBirthdate, validatePhone都不会运行。系统直接将错误返回用户，用户要先改正了第一个错误再提交后系统继续下一个字段的验证。如果需要填写多个字段的信息表格什么的就更凸显麻烦了。如果我们用Applicative风格：

```1 apply(apply(apply((WebForm(_, _, _)).curried)(
2   validateName(field1)))(
3   validateBirthdate(field2)))(
4   validatePhone(field3))```

```1 trait Validation[+E,+A]
2 case class Failure[E](head: E, tail: Vector[E]) extends Validation[E,Nothing]
3 case class success[A](a: A) extends Validation[Nothing,A]```

Validation类型的Failure可以容纳多条数据。注意 +E,+A使我们可以代入Nothing: Validate[E,Nothing],Validation[Nothing,A]。

``` 1 implicit def validationApplicative[E] = new Applicative[({type l[A] = Validation[E,A]})#l] {
2     def unit[A](a: A) = Success(a)
3   def map2[A,B,C](fa: Validation[E,A], fb: Validation[E,B])(f: (A,B) => C): Validation[E,C] = {
4     (fa,fb) match {
5         case (Success(a),Success(b)) => Success(f(a,b))
6         case (Failure(h1,t1),Failure(h2,t2)) => Failure(h1, t1 ++ Vector(h2) ++ t2)
7         case (e@Failure(_,_),_) => e
8         case (_,e@Failure(_,_)) => e
9     }
10   }
11 }```

map2+unit是Applicative的最基本组件函数。我们只要实现这两个函数就行了。

``` 1 trait Validation[+E,+A]
2 case class Failure[E](head: E, tail: Vector[E]) extends Validation[E,Nothing]
3 case class Success[A](a: A) extends Validation[Nothing,A]
4 implicit def validationApplicative[E] = new Applicative[({type l[A] = Validation[E,A]})#l] {
5     def unit[A](a: A) = Success(a)
6   def map2[A,B,C](fa: Validation[E,A], fb: Validation[E,B])(f: (A,B) => C): Validation[E,C] = {
7     (fa,fb) match {
8         case (Success(a),Success(b)) => Success(f(a,b))
9         case (Failure(h1,t1),Failure(h2,t2)) => Failure(h1, t1 ++ Vector(h2) ++ t2)
10         case (e@Failure(_,_),_) => e
11         case (_,e@Failure(_,_)) => e
12     }
13   }
14 }
15 import java.util.Date
16 case class WebForm(name: String, birthdate: Date, phone: String)
17
18 def validateName(name: String): Validation[String, String] = {
19   if (name != "")
20        Success(name)
21   else Failure("Name cannot be empty", Vector())
22 }
23
24 def validateBirthdate(birthdate: String): Validation[String, Date] = {
25   try {
26     import java.text._
27     Success((new SimpleDateFormat("yyyy-MM-dd")).parse(birthdate))
28   } catch {
29     case e => Failure("Birthdate must be in the form yyyy-MM-dd", Vector())
30   }
31 }
32 def validatePhone(phoneNumber: String): Validation[String, String] = {
33   if (phoneNumber.matches("[0-9]{10}"))
34        Success(phoneNumber)
35   else Failure("Phone number must be 10 digits", Vector())
36 }
37 def validateWebForm(name: String, birthdate: String, phone: String): Validation[String, WebForm] = {
38     apply(validateName(name))
39      (apply(validateBirthdate(birthdate))
40      (apply(validatePhone(phone))((WebForm(_,_,_)).curried)))))
41 }```

0 条评论

## 相关文章

### C++ STL算法系列5---equal() , mismatch()

equal和mismatch算法的功能是比较容器中的两个区间内的元素。这两个算法各有3个参数first1,last1和first2.如果对 于区间[first1...

23180

19530

20290

34050

### 《剑指Offer》附加题_用两个队列实现一个栈_C++版

在《剑指Offer》中，在栈和队列习题中，作者留下来一道题目供读者自己实现，即“用两个队列实现一个栈”。 　　在计算机数据结构中，栈的特点是后进先出，即最后...

32550

15430

17930

### (转)Java--栈与队列

Java中栈与队列相比集合来说不是很常用的数据结构,因此经常被忽略.个人觉得还是有必要掌握下,以备不时之需. Java中实际上提供了java.util.Stac...

66930

323100

### LWC 55：712. Minimum ASCII Delete Sum for Two Strings

LWC 55：712. Minimum ASCII Delete Sum for Two Strings 传送门：712. Minimum ASCII Dele...

23470