アレッ*_*ックス 36 monads haskell functional-programming scala maybe
我知道monad是什么以及如何使用它们.我不明白的是,是什么让Option
一个单子?
在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 { ... }
Run Code Online (Sandbox Code Playgroud)
没有任何与monad相关的东西.
如果我在Scala中创建自己的类,默认情况下它是monad吗?为什么不?
Gab*_*lla 56
Monad
是一个概念,如果你愿意,它是一个抽象的接口,它只是定义了一种组合数据的方式.
Option
支持组合通过flatMap
,这几乎是穿"monad徽章"所需的一切.
从理论的角度来看,它还应该:
unit
操作(return
在Haskell术语中)从一个裸值创建一个monad,如果Option
是Some
构造函数但这并不是Scala严格执行的.
scala中的Monads是一个更宽松的概念,在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
}
Run Code Online (Sandbox Code Playgroud)
如你所见,我们只是实施map
和flatMap
(以及toString
作为商品).恭喜,我们有一个monad!我们来试试吧:
scala> for {
a <- new MyMonad(2)
b <- new MyMonad(3)
} yield a + b
// res1: MyMonad[Int] = 5
Run Code Online (Sandbox Code Playgroud)
太好了!我们没有进行任何过滤,因此我们不需要实现withFilter
.此外,由于我们正在产生价值,我们也不需要foreach
.基本上你实现了你想要支持的任何东西,没有严格的要求.如果您尝试过滤for-comprehension并且尚未实现withFilter
,则只会出现编译时错误.
Ion*_*tan 13
任何(部分)实现的东西,通过鸭子打字,FilterMonadic
特征被认为是Scala中的monad.这与在Haskell中表示monad或Monad
在scalaz中表示类型类的方式不同.但是,为了使for
Scala 中的理解语法糖受益,对象必须暴露FilterMonadic
特征中定义的一些方法.
此外,在Scala中,Haskell return
函数的等价物是yield
用于从for
理解中生成值的关键字.desugaring yield
是map
对"monad"方法的调用.
我所说的方式是,monads作为一种设计模式与一流的抽象之间正在出现区别.Haskell以Monad
类型类的形式具有后者.但是如果你的类型具有(或可以实现)monadic操作并遵守法律,那么这也是一个monad.
现在,您可以在Java 8的库中看到monads作为设计模式.Java 8中的Optional
和Stream
类型带有一个of
与Haskell对应的静态方法return
和一个flatMap
方法.但是没有Monad
类型.
介于两者之间你也有"鸭式"的方法,正如IonuţG.Stan的回答所说的那样.C#也有这个 - LINQ语法不依赖于特定类型,而是可以与任何实现某些方法的类一起使用.