设为首页 加入收藏

TOP

Scalaz(25)- Monad: Monad Transformer-叠加Monad效果(三)
2017-10-10 12:13:21 】 浏览:7727
Tags:Scalaz Monad Transformer- 叠加 效果
t;
.point[Result] 10 s3 <- getResult.liftM[OptionT] 11 } yield s1+s2+s3 //> prg : Exercises.monadtxns.Result[String] = OptionT(\/-(Some(Hello World,how 12 //| are you!))) 13 prg.run //> res0: Exercises.monadtxns.Error[Option[String]] = \/-(Some(Hello World,how a 14 //| re you!))

首先,我们避免了stair-stepping,直接运算s1+s2+s3。point、OptionT.optionT、liftM分别对String,Option,Either进行类型升格形成Result[String] >>> OptionT[Error,String]。升格函数源代码如下:

trait ApplicativeIdV[A] extends Ops[A] { def point(implicit F: Applicative[F]): F[A] = Applicative[F].point(self) ... trait OptionTFunctions { def optionT[M[_]] = new (({type λ[α] = M[Option[α]]})#λ ~> ({type λ[α] = OptionT[M, α]})#λ) { def apply[A](a: M[Option[A]]) = new OptionT[M, A](a) } ... final class MonadOps[F[_],A] private[syntax](val self: F[A])(implicit val F: Monad[F]) extends Ops[F[A]] { ////
 def liftM[G[_[_], _]](implicit G: MonadTrans[G]): G[F, A] = G.liftM(self) ...

再看看组合的Monad是否实现了功能叠加,如果我们加个None转换:

1 val prg: Result[String] = for { 2   s1 <- OptionT.optionT(getString.point[Error]) 3   s0 <- OptionT(none[String].point[Error]) 4   s2 <- "World,".point[Result] 5   s3 <- getResult.liftM[OptionT] 6 } yield s1+s2+s3                                  //> prg : Exercises.monadtxns.Result[String] = OptionT(\/-(None))
7 prg.run                                           //> res0: Exercises.monadtxns.Error[Option[String]] = \/-(None)

加个Left效果:

1 val prg: Result[String] = for { 2   s1 <- OptionT.optionT(getString.point[Error]) 3   s0 <- OptionT("Catch Error!".left: Error[Option[String]]) 4   s2 <- "World,".point[Result] 5   s3 <- getResult.liftM[OptionT] 6 } yield s1+s2+s3                                  //> prg : Exercises.monadtxns.Result[String] = OptionT(-\/(Catch Error!))
7 prg.run                                           //> res0: Exercises.monadtxns.Error[Option[String]] = -\/(Catch Error!)

的确,用Monad Transformer组合Monad后可以实现成员Monad的效果叠加。

不过,在实际应用中两层以上的Monad组合还是比较普遍的。Monad Transformer本身就是Monad,可以继续与另一个Monad组合,只要用这个Monad的Transformer就行了。例如我们在上面的例子里再增加一层State,最终形成一个三层类型:State[Either[Option[A]]]。按照上面的经验,堆砌Monad是由内向外的,我们先组合 StateEither >>> StateT[Either,A],然后再得出组合:OptionT[StateEither,A]。我们来示范一下:

先重新命名(alias)一些类:

type StringEither[A] = String \/ A type StringEitherT[M[_],A] = EitherT[M,String,A] type IntState[A] = State[Int,A] type IntStateT[M[_],A] = StateT[M,Int,A] type StateEither[A] = StringEitherT[IntState,A] type StateEitherOption[A] = OptionT[StateEither,A]

由Option,Either,State组合而成的Monad需要相关的升格函数(lifting functions):

//常量升格
val m: StateEitherOption[Int] = 3.point[StateEitherOption] //> m : Exercises.monad_txnfm.StateEitherOption[Int] = OptionT(EitherT(scalaz.p //| ackage$StateT$$anon$1@4f638935)) //option类升格
val o: Option[Int] = 3.some                       //> o : Option[Int] = Some(3)
val o1: StateEither[Option[Int]]= o.point[StateEither] //> o1 : Exercises.monad_txnfm.StateEither[Option[Int]] = EitherT(scalaz.packag //| e$StateT$$anon$1@694abbdc)
 val o2: StateEitherOption[Int] = OptionT.optionT(o1) //> o2 : Exercises.monad_txnfm.StateEitherOption[Int] = OptionT(EitherT(scalaz. //| package$StateT$$anon$1@694abbdc)) //val o2: OptionT[StateEither,Int] = OptionT.optionT(o1) //either类升格
val e: StringEither[Int] = 3.point[StringEither]  //> e : Exercises.monad_txnfm.StringEither[Int] = \/-(3)
val e1: IntState[StringEither[Int]] = e.point[IntStat
首页 上一页 1 2 3 4 5 下一页 尾页 3/5/5
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Scalaz(26)- Lens: 函数式不.. 下一篇Scalaz(27)- Inference & Unap..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目