关于泛型:Scala 中的 Monad trait

Monad trait in Scala

(如何)在 Scala 中以通用方式表示 monad 是可能的(比如 Haskell 中的 Monad 类型类)?是否可以为此目的定义 trait Monad


你可以试试这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
trait Monad[+M[_]] {
  def unit[A](a: A): M[A]
  def bind[A, B](m: M[A])(f: A => M[B]): M[B]
}

// probably only works in Scala 2.8
implicit def monadicSyntax[M[_], A](m: M[A])(implicit tc: Monad[M]) = new {
  private val bind = tc.bind(m) _

  def map[B](f: A => B) = bind(f compose tc.unit)

  def flatMap[B](f: A => M[B]) = bind(f)
}

implicit object MonadicOption extends Monad[Option] {
  def unit[A](a: A) = Some(a)

  def bind[A, B](opt: Option[A])(f: A => Option[B]) = opt flatMap f
}

您当然会为您心中想要的任何其他 monad 定义类似的隐式对象。在 Haskell 术语中,您可以将 Monad 视为类型类,将 MonadicOption 视为该类型类的特定实例。 monadicSyntax 隐式转换只是演示了如何使用此类型类来允许将 Scala\\ 的 for 推导式用于满足 Monad 类型类的任何内容。

一般来说,Scala 标准库中实现 flatMap 的大多数东西都是 monad。 Scala 没有定义通用的 Monad 类型类(尽管那会非常有用)。相反,它依赖于解析器的句法技巧,以允许将 for 推导用于实现适当方法的任何内容。具体来说,这些方法是 mapflatMapfilter(或 foreachfilter 用于命令式)。


您可能会发现 scalaz 项目很有趣;除了 monad 的实现之外,它还有许多其他(功能性)的东西。


http://www.codecommit.com/blog/ruby/monads-are-not-metaphors

这是 Daniel 撰写的关于 Monad 模式及其在 Scala 中的实现的有用且相当冗长的文章,他为此问题撰写了公认的答案。

(对于那些通过 StackOverflow 网站搜索的神秘方式偶然发现这个"古老"问题的人。)


看看 http://www.scala-lang.org/api/current/index.html#scala.collection.generic.FilterMonadic。一个 case 类已经内置到语言中,并在整个集合中广泛使用...


Scala 通过使用隐式参数,尤其是视图边界和上下文边界,获得了与 Haskell 类型类类似的能力。你可以看到这些东西在 Scala 2.8 上特别有用,具有像 OrderingNumeric.

这样的特征

也就是说,看看 Scalaz 项目。它有单子、函子、箭头……整个shebang。