我知道 monad 是什么以及如何使用它们。我不明白的是什么使得Option
成为一个monad?
在 Haskell 中,monad Maybe
是一个 monad,因为它是从 Monad
类实例化的(该类至少有 2 个必要的函数 return
和 bind
使类 Monad
实际上成为一个 monad)。
但是在 Scala 中我们有这个:
sealed abstract class Option[+A] extends Product with Serializable { ... }
trait Product extends Any with Equals { ... }
与单子(monad)无关。
如果我在 Scala 中创建自己的类,默认情况下它会是一个 monad 吗?为什么不呢?
最佳答案
Monad
是一个概念,如果你愿意的话,它是一个抽象接口(interface),它简单地定义了一种组合数据的方式。
Option
支持通过 flatMap
进行组合,这几乎是佩戴“monad 徽章”所需的一切。
从理论角度来看,它还应该:
- 支持
unit
操作(return
,用 Haskell 术语来说)以从裸值创建 monad,在Option
的情况下是Some
构造函数 - 尊重monadic laws
但这并没有被 Scala 严格执行。
scala 中的 Monad 是一个比 Haskell 中宽松得多的概念,并且方法更实用。 从语言的角度来看,单子(monad)唯一相关的是在 for 理解中使用的能力。
flatMap
是基本要求,您可以可选提供 map
、withFilter
和 foreach
.
但是,不存在像 Haskell 那样严格遵守 Monad
类型类的情况。
这是一个示例:让我们定义自己的 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
作为商品)。
恭喜,我们有了一个 monad!让我们尝试一下:
scala> for {
a <- new MyMonad(2)
b <- new MyMonad(3)
} yield a + b
// res1: MyMonad[Int] = 5
不错!我们没有进行任何过滤,因此不需要实现withFilter
。另外,由于我们正在生成一个值,因此我们也不需要 foreach
。基本上你可以实现任何你想支持的东西,没有严格的要求。如果您尝试在 for 理解式中进行过滤,但尚未实现 withFilter
,您只会收到编译时错误。
关于scala - 到底是什么让 Option 成为 Scala 中的 monad?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25361203/