Monad
是一个概念,如果你愿意的话,是一个抽象接口,它简单地定义了一种组合数据的方式。
Option
通过 支持组合flatMap
,这几乎就是佩戴“monad 徽章”所需的一切。
从理论上讲,它还应该:
- 支持一个
unit
操作(return
在 Haskell 术语中)从一个裸值创建一个 monad,在这种情况下Option
是Some
构造函数
- 尊重一元法则
但这并不是 Scala 严格执行的。
scala 中的 Monad 是一个比 Haskell 更宽松的概念,而且这种方法更实用。从语言的角度来看,monad 唯一相关的是用于理解的能力。
flatMap
是一项基本要求,您可以选择提供map
和。withFilter
foreach
然而,没有Monad
像在 Haskell 中那样严格遵守类型类。
这是一个例子:让我们定义我们自己的 monad。
class MyMonad[A](value: A) {
def map[B](f: A => B) = new MyMonad(f(value))
def flatMap[B](f: A => MyMonad[B]) = f(value)
override def toString = value.toString
}
如您所见,我们只是在实施map
和flatMap
(好吧,并且toString
作为商品)。恭喜,我们有一个单子!让我们试一试:
scala> for {
a <- new MyMonad(2)
b <- new MyMonad(3)
} yield a + b
// res1: MyMonad[Int] = 5
好的!我们没有做任何过滤,所以我们不需要实现withFilter
. 此外,由于我们正在产生一个值,因此我们也不需要foreach
。基本上你可以实现任何你想支持的东西,没有严格的要求。如果您尝试在 for-comprehension 中进行过滤并且您还没有实现withFilter
,那么您只会得到一个编译时错误。