我试图以更实际的方式理解monad和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的特例)?
答案 0 :(得分:4)
如果使用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]
}
加入是Scala的flatten
,绑定是Scala的flatMap
。
请注意,要仅使用unit
和flatten/join
定义monad,您还必须提供方法map[A](m: M[A])(f: A => B): M[B]
。这是因为monad实际上是一个(endo)仿函数,具有两个自然变换,单位和连接。由于它是一个仿函数,因此它具有map
功能。根据您的代码设计,map
应与Monad特征中的unit
和join
一起定义,或者从Monad特征扩展的Functor特征继承。
为了完整起见,让我说明定义monad的所有三种可能方式:
所有三个都可以使用另外两个中的一个来表达。我将跳过代码来演示这一点,因为它与问题没有直接关系,但如果需要,我可以在编辑中添加它。