究竟是什么让选项在斯卡拉monad?

我知道monads是什么以及如何使用它们。 我不明白的是,让我们说, Option一个monad?

在Haskell中,一个monad Maybe是一个monad,因为它是从Monad类实例化的(至less有两个必要的函数returnbind ,使得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提供mapwithFilterforeach

    然而,像Haskell一样,没有像Monadtypestypes严格一致的东西。

    下面是一个例子:让我们定义我们自己的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 } 

    正如你所看到的,我们只是实现了mapflatMap (以及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中是Monadtypestypes是不同的 。 但是,为了使Scala中的理解句法糖受益,一个对象必须暴露FilterMonadic特征中定义的一些方法。

    另外,在Scala中,Haskell return函数的等价物是用于从理解中产生值的yield关键字。 yield的解除是对“monad”的map方法的一个调用。

    我所说的方式是,monads作为一种devise模式一stream的抽象之间正在出现一种新的区别。 哈斯克尔有后者,以Monadtypes的forms。 但是,如果你有一种types的(或可以实现)一元操作并服从法律,那也是一个单子。

    现在,您可以在Java 8的库中看到monad作为devise模式。 Java 8中的OptionalStreamtypes带有一个对应于Haskell return的静态方法和一个flatMap方法。 但是没有Monadtypes。

    在IonuţG. Stan的回答中,你也有一种“鸭子式”的方法。 C#也有这个–LINQ语法不是绑定到一个特定的types,而是它可以与任何实现某些方法的类一起使用。