Option Monad
Scala中的Option是一个Monad实现。
Option的简化版定义如下:
sealed abstract class Option[+A] {
def isEmpty: Boolean
def get: A
def map[B](f: A => B): Option[B] =
if(isEmpty) None else Some(f(this.get))
def flatMap[B](f: A => Option[B]): Option[B] =
if(isEmpty) None else f(this.get)
}
final case class Some[+A](x: A) extends Option[A] {
def isEmpty: false
def get = x
}
final case class None extends Option[Nothing] {
def isEmpty = true
def get = throw new NoSuchElementException("None.get")
}
代码中,Option定义了flatMap,Some和None都被定义为case class,所以其名字就是构造器,无需定义unit函数。
Option可以看成是只有一个元素的容器:
- map的工作就是对仅有的一个元素进行f调用,然后将结果打包成Option
- flatMap的工作是对一个元素进行f调用,产生的结果已经是Option实例,并且没有其他的结果需要flatten
None的存在是唯一的插曲,map和flatMap对于None要做的额外工作就是检查自己是不是None,如果是,则直接返回None。因为None表示一个空的容器,因此不能进行其他的计算。
用Monad规则验证Option
对于Option,unit(x) == Some(x)。下面是Option的flatMap构造:
def flatMap[U](f: T => Option[U]): Option[U] = this match {
case Some(x) => f(x)
case None => None
}
我们先证明Some(x) flatMap f == f(x)
:
Some(x) flatMap f
== Some(x) match {
case Some(x) => f(x)
case None => None
}
== f(x)
然后我们证明opt flatMap Some == opt
:
opt flatMap Some
== opt match {
case Some(x) => Some(x)
case None => None
}
== opt
这里,我们看到对一个Option对象opt进行flatMap操作,
其中映射函数式Some构造函数时,返回的是初始时的opt
我们还要证明opt flatMap f flatMap g == opt flatMap (x => f(x) flatMap g)
:
opt flatMap f flatMap g
== opt match { case Some(x) => f(x) case None => None}
match { case Some(y) => g(y) case None => None}
如果将第二个match表达式嵌入第一个match表达式中,将得到
== opt match {
case Some(x) =>
f(x) match {case Some(y) => g(y) case None => None}
case None =>
None match {case Some(y) => g(y) case None => None}
}
== opt match {
case Some(x) =>
f(x) match {case Some(y) => g(y) case None => None}
case None => None
}
== opt match {
case Some(x) => f(x) flatMap g
case None => None
}
== opt flatMap (x => f(x) flatMap g)
转载请注明作者Jason Ding及其出处
jasonding.top
Github博客主页(http://blog.jasonding.top/)
CSDN博客(http://blog.csdn.net/jasonding1354)
简书主页(http://www.jianshu.com/users/2bd9b48f6ea8/latest_articles)
Google搜索jasonding1354进入我的博客主页