设为首页 加入收藏

TOP

Scalaz(12)- Monad:再述述flatMap,顺便了解MonadPlus(三)
2017-10-10 12:13:33 】 浏览:2446
Tags:Scalaz Monad flatMap 顺便 了解 MonadPlus
又定义了抽象成员plus[A],那么获取MonadPlus实例必须实现empty[A]: F[A]和plus[A](a: F[A], b: F[A]): F[A]。看来这个PlusEmpty就是一种Monoid,只不过是针对高阶类型的。我们知道Monad实例类型必须是高阶的M[_],那么如果Monad实例同时又具备Monoid特性的话,那么就可以使用MonadPlus来描述它的性质。

好了,现在我想获取KeyLog[K]的MonadPlu实例,那么我必须实现empty[A]:F[A]和plus[A](a:F[A],b:F[A]):F[A]。KeyLog[K]的empty[K]是什么呢?想了半天没得到答案,可能KeyLog[K]就没有empty[K]吧。也许我们想取得KeyLog MonadPlu实例的目的还没搞清楚。看看上面的需求:

1 for { 2  a <- enterInt(3) 3  b <- enterInt(4)  if b > 0
4  c <- enterStr("Result:") 5 } yield c + (a * b).toString

从字面上看是希望通过守卫函数过滤数字为0的数字。等等,enterInt(4)已经确定了输入为4,是 > 0,还过滤什么?不是找事吗。所以我们的目的应该聚焦在过滤需求上。Scalaz为List,Option提供了MonadPlus实例,我们看看这两种类型的守卫函数使用:

 1 for { //list
 2     a <- 1 |-> 50 if a.shows contains '7'
 3 } yield a                                         //> res5: List[Int] = List(7, 17, 27, 37, 47)
 4 for { //option
 5     a <- Some(3)  6     b <- Some(4) if a < b  7 } yield b                                         //> res6: Option[Int] = Some(4)
 8 for { //option
 9     a <- Some(3) 10     b <- Some(4) if a > b 11 } yield b                                         //> res7: Option[Int] = None

先来分析List例子:一个List可能是空的,又可能有多过一个元素,有多种可能。守卫函数的功能就是在这些可能里进行选择。

再分析Option:可能是None或者Some,这本身就是一种筛选。对于KeyLog[K],它只有一种状态,没有选择的需要,所以我无法实现KeyLog[K]的empty[K]。

List和Option的empty分别是:Nil和None,这个很容易理解。那么plus呢?把 plus(list1,list2):list3 = list1 ++ list2这个倒是容易理解,但plus(option1,option2):option3这个又应该怎么理解呢?我们还是看看在scalaz里是怎么定义plus的吧:scalaz.std/List.scala

1   implicit val listInstance = new Traverse[List] with MonadPlus[List] with Each[List] with Index[List] with Length[List] with Zip[List] with Unzip[List] with Align[List] with IsEmpty[List] with Cobind[List] { 2 ... 3     def empty[A] = Nil 4     def plus[A](a: List[A], b: => List[A]) = a ++ b 5 ...

List的plus就是把两个List接起来(concat)

scalaz.std/Option.scala

1   implicit val optionInstance = new Traverse[Option] with MonadPlus[Option] with Each[Option] with Index[Option] with Length[Option] with Cozip[Option] with Zip[Option] with Unzip[Option] with Align[Option] with IsEmpty[Option] with Cobind[Option] with Optional[Option] { 2 ... 3     def empty[A]: Option[A] = None 4     def plus[A](a: Option[A], b: => Option[A]) = a orElse b 5 ...

Option的plus意思是如果a是None就取b否则取a,无论b是否None。我们用MonadPlus提供的操作符号<+>来示范:

1 List(1,2,3) <+> List(4,5,6)                       //> res4: List[Int] = List(1, 2, 3, 4, 5, 6)
2 Nil <+> List(1,2,3)                               //> res5: List[Int] = List(1, 2, 3)
3 List(1,2,3) <+> Nil                               //> res6: List[Int] = List(1, 2, 3)
4 none <+> 2.some                                   //> res7: Option[Int] = Some(2)
5 2.some <+> 3.some                                 //> res8: Option[Int] = Some(2)
6 2.some <+> none                                   //> res9: Option[Int] = Some(2)
7 none <+> none                                     //> res10: Option[Nothing] = None

 为了实现KeyLog MonadPlus实例,我们必须对KeyLog类型重新定义使之包含多过一种状态:

 1 import scalaz._  2 import Scalaz._  3 object keylog {  4 trait KeyLog[+K] {  5   override def toString = this match {  6     case KeyIn(value,log) => "["+value+","+log+"]"
 7     case _ => "[Keypad Locked]"
 8  }  9   def mapLog(preLog: String): KeyLog[K] = this match { 10     case KeyIn(value,log) => KeyIn(value,preLog +";"+log) 11     case _ => KeyLock 12  } 13   def flatMap[I](f: K => KeyLog[I]): KeyLog[I] = this match { 14     case KeyIn(value,log) => f(value).mapLog(log) 15     case _ => KeyLock 16  } 17 } 18 case class KeyIn[K](value: K, log: String) extends KeyLog[K] 19 case object KeyLock extends KeyLog[Nothing] 20 object KeyLog { 21 /* def apply[K](k: K, msg
首页 上一页 1 2 3 4 下一页 尾页 3/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇spark视频课程下载链接 下一篇Scalaz(13)- Monad:Writer - ..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目