究竟是什么让选项在斯卡拉monad?
我知道monads是什么以及如何使用它们。 我不明白的是,让我们说, Option
一个monad?
在Haskell中,一个monad Maybe
是一个monad,因为它是从Monad
类实例化的(至less有两个必要的函数return
并bind
,使得Monad
类实际上是一个monad)。
但在斯卡拉我们有这样的:
sealed abstract class Option[+A] extends Product with Serializable { ... } trait Product extends Any with Equals { ... }
没有关系到monad。
如果我在Scala中创build自己的类,默认情况下会是monad吗? 为什么不?
Monad
是一个概念,如果你愿意的话,它是一个抽象的接口,它只是定义了一个数据组成的方式。
Option
通过flatMap
支持合成,这几乎是佩戴“monad徽章”所需的一切。
从理论angular度来看,还应该:
- 支持一个
unit
操作(以Haskell的方式return
)从一个裸值创build一个monad,在Option
情况下是Some
构造函数 - 尊重一元法律
但这不是由斯卡拉严格执行。
在斯卡拉Monad是一个在Haskell更松散的概念,这种方法更实用。 从语言的angular度来说,monad唯一相关的就是用于理解的能力。
flatMap
是一个基本要求,你可以select提供map
, withFilter
和foreach
。
然而,像Haskell一样,没有像Monad
typestypes严格一致的东西。
下面是一个例子:让我们定义我们自己的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-comprehension中进行过滤,并且您没有使用withFilter
实现,则只会收到编译时错误。
任何(部分地)通过鸭子input实现的FilterMonadic
特性被认为是Scala中的monad。 这与单子如何在Haskell中表示或者在scalaz中是Monad
typestypes是不同的 。 但是,为了使Scala中的理解句法糖受益,一个对象必须暴露FilterMonadic
特征中定义的一些方法。
另外,在Scala中,Haskell return
函数的等价物是用于从理解中产生值的yield
关键字。 yield
的解除是对“monad”的map
方法的一个调用。
我所说的方式是,monads作为一种devise模式与一stream的抽象之间正在出现一种新的区别。 哈斯克尔有后者,以Monad
types的forms。 但是,如果你有一种types的(或可以实现)一元操作并服从法律,那也是一个单子。
现在,您可以在Java 8的库中看到monad作为devise模式。 Java 8中的Optional
和Stream
types带有一个对应于Haskell return
的静态方法和一个flatMap
方法。 但是没有Monad
types。
在IonuţG. Stan的回答中,你也有一种“鸭子式”的方法。 C#也有这个–LINQ语法不是绑定到一个特定的types,而是它可以与任何实现某些方法的类一起使用。