设为首页 加入收藏

TOP

Scalaz(12)- Monad:再述述flatMap,顺便了解MonadPlus(二)
2017-10-10 12:13:33 】 浏览:2440
Tags:Scalaz Monad flatMap 顺便 了解 MonadPlus
一下flatMap
 

1 KeyLog(3,"Entered Number 3").flatMap(a => KeyLog("Hello", "Entered String 'Hello'")) 2                                                   //> res2: Exercises.keylog.KeyLog[String] = [Hello,Entered Number 3;Entered Stri 3                                                   //| ng 'Hello']

最终log值:"Entered Number 3;Entered String 'Hello'。我们实现了在运算flatMap过程中对log进行的累积。

现在我们可以先获取KeyLog的Monad实例,然后进行flatMap串联及使用for-comprehension进行行令编程了:

 1 object KeyLog {  2     def apply[K](k: K, msg: String): KeyLog[K] = new KeyLog[K] {  3         def value = k  4         def log = msg  5  }  6 import scalaz._  7 import Scalaz._  8     implicit object keylogMonad extends Monad[KeyLog] {  9         def point[K](k: => K): KeyLog[K] = KeyLog(k,"") 10         def bind[K,I](kk: KeyLog[K])(f: K => KeyLog[I]): KeyLog[I] = kk flatMap f 11  } 12 }

在KeyLog Monad实例里bind使用了我们设计的flatMap函数。看看flatMap串接和for-comprehension效果:

def enterInt(k: Int): KeyLog[Int] = KeyLog(k, "Number:"+k.toString) //> enterInt: (k: Int)Exercises.keylog.KeyLog[Int]
def enterStr(k: String): KeyLog[String] = KeyLog(k,"String:"+k) //> enterStr: (k: String)Exercises.keylog.KeyLog[String]
enterInt(3) >>= {a => enterInt(4) >>= {b => enterStr("Result:") map {c => c + (a * b).toString} }} //> res3: Exercises.keylog.KeyLog[String] = [Result:12,Number:3;Number:4;String: //| Result:;]
for { a <- enterInt(3) b <- enterInt(4) c <- enterStr("Result:") } yield c + (a * b).toString                      //> res4: Exercises.keylog.KeyLog[String] = [Result:12,Number:3;Number:4;String //| :Result:;]

value和log都按照要求实现了转变。

在使用for-comprehension时突然想到守卫函数(guard function)。我想既然已经得到了KeyLog的Monad实例,是不是可以在它的for-comprehension里使用守卫函数呢?就像这样:

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

不过无法通过编译。提示需要filter函数。查了一下MonadPlus typeclass可以提供这个函数。那么我们就沿着惯用的套路获取一下KeyLog的MonadPlus实例。MonadPlus trait的定义如下:scalaz/MonadPlus.scala

 1 trait MonadPlus[F[_]] extends Monad[F] with ApplicativePlus[F] { self =>
 2   ////
 3 
 4   /** Remove `f`-failing `A`s in `fa`, by which we mean: in the  5  * expression `filter(filter(fa)(f))(g)`, `g` will never be invoked  6  * for any `a` where `f(a)` returns false.  7     */
 8   def filter[A](fa: F[A])(f: A => Boolean) =
 9     bind(fa)(a => if (f(a)) point(a) else empty[A]) 10 ...

MonadPlus又继承了ApplicativePlus:scalar/ApplicativePlus.scala

1 trait ApplicativePlus[F[_]] extends Applicative[F] with PlusEmpty[F] { self =>

ApplicativePlus又继承了PlusEmpty: scalaz/PlusEmpty.scala 

1 trait PlusEmpty[F[_]] extends Plus[F] { self =>
2   ////
3  def empty[A]: F[A] 4 ...

PlusEmpty定义了抽象成员empty[A],又继承了Plus: scalar/Plus.scala

 1 trait Plus[F[_]]  { self =>
 2   ////
 3 
 4   /**The composition of Plus `F` and `G`, `[x]F[G[x]]`, is a Plus */
 5   def compose[G[_]](implicit G0: Plus[G]): Plus[({type λ[α] = F[G[α]]})#λ] = new CompositionPlus[F, G] {  6     implicit def F = self  7 
 8     implicit def G = G0  9  } 10 
11   /**The product of Plus `F` and `G`, `[x](F[x], G[x]])`, is a Plus */
12   def product[G[_]](implicit G0: Plus[G]): Plus[({type λ[α] = (F[α], G[α])})#λ] = new ProductPlus[F, G] { 13     implicit def F = self 14 
15     implicit def G = G0 16  } 17 
18   def plus[A](a: F[A], b: => F[A]): F[A] 19 
20   def semigroup[A]: Semigroup[F[A]] = new Semigroup[F[A]] { 21     def append(f1: F[A], f2: => F[A]): F[A] = plus(f1, f2) 22  } 23 ...

Plus

首页 上一页 1 2 3 4 下一页 尾页 2/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇spark视频课程下载链接 下一篇Scalaz(13)- Monad:Writer - ..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目