-
Notifications
You must be signed in to change notification settings - Fork 6
Description
一、 有本书,是scala 函数编程,里面有个例子:
有两个玩家p1和p2, 写一个函数,把p1,p2中得分高的打印出来。如下:
case class Player(name:String,score:Int) //这是一个Player的类,有两个属性,玩家姓名和得分
def contest(p1:Player,p2:Player):Unit =
if(p1.score > p2.score)
println("${p1.name} is the winner!") //玩家1是赢家
else if (p2.score >p1.score)
println("$(p2.name} is the winner!") //玩家2是赢家
else
println("It'a draw") //平局
上面的代码中,println函数是有副作用的,因为是要输出到IO里。
所以导致contest 这个方法是不纯的,有副作用,不容易测试。于是认为,需要把这个函数contest 进行修改,抽象出不纯的,变成一个由若干个纯函数组合模式。可以采用monad单子来抽象。
改进后的代码如下:
二、
case class Player(name:String,score:Int)
1.//trait类似于接口,只定义了一个方法,返回为空的意思。 描述有一个IO动作,至于这个动作什么时候执行,如何执行,则由外部来完成。
trait IO {def run:Unit}
2.纯函数,只返回赢家这个对象
def winner(p1:Player,p2:Player):Option[Player]= //Option有点类似于haskell中的Maybe
if(p1.score >p2.score) Some(p1)
else if (p1.score<p2.score ) Some(p2)
else None //平局
-
//生成赢家所要打印出来的信息串
def winnerMsg(p:Option[player]) :Unit= p map {
case Player(name,_) => "$name is the winner" //模式匹配,生成赢家的要打印的信息
} getOrElse "it's a draw //不是直接调用println 输出到屏幕 -
//描述一个需要进行IO动作,具体的打印,则由系统的解释程序来完成
def PrintLine(msg:String) :IO=
new IO {def run =println(msg)}
5.最终的组合函数
def contest(p1:Player,p2:Player):IO=
PrintLine(winnerMsg(winner(p1,p2)))
于是整个contest 函数都是纯的,无副作用的,而且是可以测试的。
但是这里没有看到与单子的影子呀?
单子不是用来剥离副作用的吗?怎么个剥离呢?
你怎么理解?