设为首页 加入收藏

TOP

Scalaz(13)- Monad:Writer - some kind of logger(二)
2017-10-10 12:13:31 】 浏览:6327
Tags:Scalaz Monad Writer some kind logger
me(3)
") 3 ob <- 4.some applyLog Vector("Entered Some(4)") 4 } yield ^(oa,ob){_ * _} //> res0: Exercises.logger.Logger[scala.collection.immutable.Vector[String],Opti 5 //| on[Int]] = Logger(Vector(Entered Some(3), Entered Some(4)),Some(12))

 一样可以使用。注意oa,ob是Option类型所以必须使用^(oa,ob){...}来结合它们。

我们再来看看Logger的典型应用:一个gcd(greatest common denominator)算法例子:

 1 def gcd(x: Int, y: Int): Logger[Vector[String], Int] = {  2     if (y == 0 ) for {  3         _ <- x applyLog Vector("Finished at " + x)  4     } yield x  5     else
 6       x applyLog Vector(x.shows + " mod " + y.shows + " = " + (x % y).shows) >>= {_ => gcd(y, x % y) }  7       
 8 }                                                 //> gcd: (x: Int, y: Int)Exercises.logger.Logger[Vector[String],Int]
 9 gcd(18,6)                                         //> res5: Exercises.logger.Logger[Vector[String],Int] = Logger(Vector(18 mod 6 10                                                   //| = 0, Finished at 6),6)
11 gcd(8,3)                                          //> res6: Exercises.logger.Logger[Vector[String],Int] = Logger(Vector(8 mod 3 = 12                                                   //| 2, 3 mod 2 = 1, 2 mod 1 = 0, Finished at 1),1)

注意 >>= 符号的使用,显现了Logger的Monad实例特性。

实际上scalar提供了Writer数据结构,它是WriterT类型的一个特例:

1 type Writer[+W, +A] = WriterT[Id, W, A]

我们再看看WriterT:scalaz/WriterT.scala

final case class WriterT[F[_], W, A](run: F[(W, A)]) { self => ...

WriterT在运算值A之外增加了状态值W,形成一个对值(paired value)。这是一种典型的FP状态维护模式。不过WriterT的这个(W,A)是在运算模型F[]内的。这样可以实现更高层次的概括,为这种状态维护的运算增加多一层运算协议(F[])影响。我们看到Writer运算是WriterT运算模式的一个特例,它直接计算运算值,不需要F[]影响,所以Writer的F[]采用了Id,因为Id[A] = A。我们看看WriterT是如何通过flatMap来实现状态维护的:scalaz/WriterT.scala:

1  def flatMap[B](f: A => WriterT[F, W, B])(implicit F: Bind[F], s: Semigroup[W]): WriterT[F, W, B] =
2  flatMapF(f.andThen(_.run)) 3 
4   def flatMapF[B](f: A => F[(W, B)])(implicit F: Bind[F], s: Semigroup[W]): WriterT[F, W, B] =
5     writerT(F.bind(run){wa =>
6       val z = f(wa._2) 7       F.map(z)(wb => (s.append(wa._1, wb._1), wb._2)) 8     })

在flatMapF函数里对(W,A)的W进行了Monoid append操作。

实际上Writer可以说是一种附加的数据结构,它在运算模型F[A]内增加了一个状态值W形成了F(W,A)这种形式。当我们为任何类型A提供注入方法来构建这个Writer结构后,任意类型的运算都可以使用Writer来实现在运算过程中增加附加作用如维护状态、logging等等。我们看看scalaz/Syntax/WriterOps.scala:

package scalaz package syntax final class WriterOps[A](self: A) { def set[W](w: W): Writer[W, A] = WriterT.writer(w -> self) def tell: Writer[A, Unit] = WriterT.tell(self) } trait ToWriterOps { implicit def ToWriterOps[A](a: A) = new WriterOps(a) }

存粹是方法注入。现在任何类型A都可以使用set和tell来构建Writer类型了:

 1 3 set Vector("Entered Int 3")                     //> res2: scalaz.Writer[scala.collection.immutable.Vector[String],Int] = WriterT  2                                                   //| ((Vector(Entered Int 3),3))
 3 "hi" set Vector("say hi")                         //> res3: scalaz.Writer[scala.collection.immutable.Vector[String],String] = Writ  4                                                   //| erT((Vector(say hi),hi))
 5 List(1,2,3) set Vector("list 123")                //> res4: scalaz.Writer[scala.collection.immutable.Vector[String],List[Int]] = W  6                                                   //| riterT((Vector(list 123),List(1, 2, 3)))
 7 3.some set List("some 3")                         //> res5: scalaz.Writer[List[String],Option[Int]] = WriterT((List(some 3),Some(3  8                                                   //| )))
 9 Vector("just say hi").tell                        //> res6: scalaz.Writer[scala.collection.immutable.Vector[String],Unit] = Writer 10                                                   //| T((Vector(just say hi),()))

用Writer运算上面Logger的例子:

1 for { 2     a <- 3 set "Entered Int 3 "
3     b <- 4 set "Entered Int 4 "
4     c <- "Result:" set "Ente
首页 上一页 1 2 3 下一页 尾页 2/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Scalaz(12)- Monad:再述述fla.. 下一篇Scalaz(14)- Monad:函数组合..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目