Scala中的Monad特征

Posted

技术标签:

【中文标题】Scala中的Monad特征【英文标题】:Monad trait in Scala 【发布时间】:2010-01-02 19:19:45 【问题描述】:

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

【问题讨论】:

【参考方案1】:

你可以试试这样的:

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-comprehensions 与任何满足 Monad 类型类的东西。

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

【讨论】:

谢谢,这正是我想要的。我只是想以一般的方式定义通用的 monad 函数和转换器...... 您实际上不会将它用于任何真实的事情,是吗? :-) 说真的,我使用 Scala 已经有一段时间了,我发现很多 Haskell 使用 Monad 类型类的情况在 Scala 中并没有出现,因为特性和子类型。上面给出的类型类虽然很酷,但肯定不是解决 Scala 问题的惯用方法。 但他们确实出现了。他们总是出现。一天几次,我想要liftA2sequenceA。当然,这些只需要 Applicative 而不是 Monad,但是,如果这些没有出现在您的编程中,那么您必须编写一些非常简单的东西。 我可能只是没有密切关注这些案件的出现。或者,我可能正在设计我的代码,以使其他解决方案更好地工作。 Scala 允许使用对象函数式解决方案来解决在 Haskell 或 ML 等语言中需要大量函数式魔法的问题(例如,使用开放递归而不是函子技巧)。 当然是真实的——想想解释器的一元表示!没有单子抽象是可怕的!【参考方案2】:

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

【讨论】:

【参考方案3】:

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

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

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

【讨论】:

【参考方案4】:

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

【讨论】:

【参考方案5】:

Scala 通过使用隐式参数(尤其是视图边界和上下文边界)实现了与 Haskell 类型类相似的功能。你可以在 Scala 2.8 上看到这些东西的使用,比如 OrderingNumeric

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

【讨论】:

以上是关于Scala中的Monad特征的主要内容,如果未能解决你的问题,请参考以下文章

Scala - 特征中的模板方法模式

Scala Slick模式特征中的“覆盖def *”是啥

Scala中monad中的重入锁

在 Scala 中混合多个特征

如何将参数注入Scala中的类/特征方法

Scala - 为使用数据库连接扩展特征/类的对象/单例编写单元测试