设为首页 加入收藏

TOP

Scalaz(10)- Monad:就是一种函数式编程模式-a design pattern(三)
2017-10-10 12:13:36 】 浏览:4662
Tags:Scalaz Monad 就是 函数 编程 模式 design pattern
.monad.Barbell = Barbell(1,0)
7 Barbell(1,0).loadRight(1) //> res9: Exercises.monad.Barbell = Barbell(1,1) 8 Barbell(2,1).loadLeft(-1) //> res10: Exercises.monad.Barbell = Barbell(1,1)

现在这个自定义类型Barbell是可以跟踪当前杠铃左右重量状态的。现在我把往杠铃上增加重量片的过程串联起来:

1 Barbell(0,0).loadLeft(1).loadRight(2).loadRight(100).loadLeft(2).loadRight(-99) 2                                                   //> res11: Exercises.monad.Barbell = Barbell(3,3)

 

可以看到这个过程中有些环节已经超出了我的能力,但杠铃最终状态好像还是合理的。我们需要在重量配置不合理的时候就立即终止。现在我们可以用Option来实现这项功能:

 1 type Discs = Int  //杠铃片数量
 2 case class Barbell(left: Discs, right: Discs) {  3   def loadLeft(n: Discs): Option[Barbell] = copy(left = left + n) match {  4     case Barbell(left,right) => if ( (left+right <= 20) && math.abs(left-right) <=3 ) Some(Barbell(left,right)) else None  5     case _ => None  6  }  7   def loadRight(n: Discs): Option[Barbell] = copy(right = right + n) match {  8     case Barbell(left,right) => if ( (left+right <= 20) && math.abs(left-right) <=3 ) Some(Barbell(left,right)) else None  9     case _ => None 10  } 11 } 12 Barbell(0,0).loadLeft(1)                          //> res8: Option[Exercises.monad.Barbell] = Some(Barbell(1,0))
13 Barbell(1,0).loadRight(1)                         //> res9: Option[Exercises.monad.Barbell] = Some(Barbell(1,1))
14 Barbell(2,1).loadLeft(-1)                         //> res10: Option[Exercises.monad.Barbell] = Some(Barbell(1,1))
15 Barbell(0,0).loadLeft(4)                          //> res11: Option[Exercises.monad.Barbell] = None
16 Barbell(15,1).loadRight(15)                       //> res12: Option[Exercises.monad.Barbell] = None

超出重量平衡的情况返回了None。现在返回值是个Option,而Option是个Monad,所以我们可以用flatMap把每个环节串联起来:

1 Barbell(0,0).loadLeft(3) >>= {_.loadRight(3)}     //> res13: Option[Exercises.monad.Barbell] = Some(Barbell(3,3))
2 Barbell(0,0).loadLeft(3) >>= {_.loadRight(3) >>= {_.loadRight(1)}} 3                                                   //> res14: Option[Exercises.monad.Barbell] = Some(Barbell(3,4))
4 Barbell(0,0).loadLeft(3) >>= {_.loadRight(3) >>= {_.loadRight(1) >>= {_.loadLeft(4)}}} 5                                                   //> res15: Option[Exercises.monad.Barbell] = Some(Barbell(7,4))
6 Barbell(0,0).loadLeft(1) >>= {_.loadRight(5) >>= {_.loadLeft(2)}} 7                                                   //> res16: Option[Exercises.monad.Barbell] = None
8 Monad[Option].point(Barbell(0,0)) >>= {_.loadLeft(3) >>= {_.loadRight(6)}} 9                                                   //> res17: Option[Exercises.monad.Barbell] = Some(Barbell(3,6))

我们的最终目的是用for-comprehension来表述,会更加清晰:

 

 1 def addWeight: Option[Barbell] = for {  2     b0 <- Monad[Option].point(Barbell(0,0))  3     b1 <- b0.loadLeft(3)  4     b2 <- b1.loadRight(3)  5 } yield b2                                        //> addWeight: => Option[Exercises.monad.Barbell]
 6 addWeight                                         //> res18: Option[Exercises.monad.Barbell] = Some(Barbell(3,3))
 7 
 8 def addWeight1: Option[Barbell] = for {  9     b0 <- Monad[Option].point(Barbell(0,0)) 10     b1 <- b0.loadLeft(4) 11     b2 <- b1.loadRight(3) 12 } yield b2                                        //> addWeight1: => Option[Exercises.monad.Barbell]
13 addWeight1                                        //> res19: Option[Exercises.monad.Barbell] = None

 

从以上的例子可以得出:实现了一个数据类型的Monad实例后就可以获取以这个类型控制运算行为的一种简单的编程语言,这种编程语言可以在for loop内部实现传统的行令编程风格。

在本篇讨论中我们介绍了Monad实际上是一种编程模式,并且示范了简单的for loop内部流程运算。在下面的一系列讨论中我们将会了解更多类型的Monad,以及Monad如何能成为功能完善的编程语言。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

首页 上一页 1 2 3 下一页 尾页 3/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Scalaz(9)- typeclass:checki.. 下一篇Scalaz(11)- Monad:你存在的..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目