Monads作为Monoids在实践中
Monads as Monoids in practice
我试图以更实际的方式理解单子和幺半群之间的关系。如果这个问题没有意义,我提前道歉,我还在挣扎。
假设我有:
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
和 join
而不是 unit
和 bind
:
编写 monad,您可能会更容易看到连接
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]
}
Join是Scala的flatten
,bind是Scala的flatMap
。
请注意,为了仅使用 unit
和 flatten/join
定义 monad,您还必须提供方法 map[A](m: M[A])(f: A => B): M[B]
。这是因为 monad 实际上是一个 (endo)functor,具有两个自然转换,unit 和 join。因为它是一个仿函数,所以它具有 map
功能。根据您的代码设计,map
应该与 unit
和 join
一起定义在您的 Monad 特征中,或者继承自某些将由您的 Monad 特征扩展的 Functor 特征。
为了完整起见,让我陈述一下定义 monad 的所有三种可能方式:
- unit + flatMap
- 单位+展平+地图
- 单位+组成
所有三个都可以用其他两个之一来表达。我将跳过代码来演示这一点,因为它与问题没有直接关系,但如果需要,我可以在编辑中添加它。
我试图以更实际的方式理解单子和幺半群之间的关系。如果这个问题没有意义,我提前道歉,我还在挣扎。
假设我有:
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
和 join
而不是 unit
和 bind
:
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]
}
Join是Scala的flatten
,bind是Scala的flatMap
。
请注意,为了仅使用 unit
和 flatten/join
定义 monad,您还必须提供方法 map[A](m: M[A])(f: A => B): M[B]
。这是因为 monad 实际上是一个 (endo)functor,具有两个自然转换,unit 和 join。因为它是一个仿函数,所以它具有 map
功能。根据您的代码设计,map
应该与 unit
和 join
一起定义在您的 Monad 特征中,或者继承自某些将由您的 Monad 特征扩展的 Functor 特征。
为了完整起见,让我陈述一下定义 monad 的所有三种可能方式:
- unit + flatMap
- 单位+展平+地图
- 单位+组成
所有三个都可以用其他两个之一来表达。我将跳过代码来演示这一点,因为它与问题没有直接关系,但如果需要,我可以在编辑中添加它。