scala - Monads 在实践中作为 Monoids

标签 scala functional-programming monads

我试图以更实际的方式理解 monads 和 monoids 之间的关系。如果这个问题没有意义,我提前道歉,我仍在挣扎。

假设例如,我有:

trait Monoid[T] {
  def zero: T
  def combine: (T,T) => T
}

和(来自 here):
trait Monad[+M[_]] {
  def unit[A](a: A): M[A]
  def bind[A, B](m: M[A])(f: A => M[B]): M[B]
}

是否可以在 Monad 和 Monoid 特征之间建立关系,例如我可以将 Monad 视为 Monoid(假设我正确理解 Monad 是 Monoid 的特例)?

最佳答案

如果您使用 unit 编写 monad,您可能会更容易看到连接。和 join而不是 unitbind :

trait Monoid[T] {
  def zero: T
  def combine: (T,T) => T
}

trait Monad[M[_]] {
  def unit[A]: A => M[A]
  def join[A]: M[M[A]] => M[A]
}

加入是Scala的flatten , 而 bind 是 Scala 的 flatMap .

请注意,为了仅使用 unit 来定义 monad和 flatten/join ,您还必须提供方法 map[A](m: M[A])(f: A => B): M[B] .这是因为 monad 实际上是一个(endo)仿函数,具有两个自然变换,unit 和 join。因为它是一个仿函数,所以它有 map功能。根据您的代码设计,map应该与 unit 一起定义和 join在你的 Monad trait 中,或者从一些 Functor trait 继承,这些 Functor trait 会被你的 Monad trait 扩展。

为了完整起见,让我说明定义 monad 的所有三种可能方式:
  • unit + flatMap
  • 单位+展平+ map
  • 单元 + 撰写

  • 所有这三个都可以使用其他两个中的一个来表示。我将跳过代码来演示这一点,因为它与问题没有直接关系,但如果需要,我可以将其添加到编辑中。

    关于scala - Monads 在实践中作为 Monoids,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41555238/

    相关文章:

    scala - 将Map [K,Option [V]]转换为Map [K,V]的更好方法

    scala - 修改 Scala AST 中的节点

    scripting - 有没有使用函数式编程的体面脚本语言?

    javascript - 返回 "then"内具有 "Promise.then()"函数的对象

    scala - 如何制作 ArrayBuffer 的 ArrayBuffer

    linux - 如何从 Scala 执行内置的 shell

    swift:无法将 [sic] 字符数组缩减为字符串

    来自具有特定类名的所有元素的 Javascript 数组

    scala - Scala : return, 本地的 Reader monad 和序列