我记得monad
是一个monoid
。也就是说,有一个关联二元运算 *
,因此如果ma
和mb
是一元值,那么ma * mb
也是一元值。
如果以上是正确的,那么Option
Scala 中的二进制操作是什么?例如,什么可以*
在Some(1) * Some(2)
?
我记得monad
是一个monoid
。也就是说,有一个关联二元运算 *
,因此如果ma
和mb
是一元值,那么ma * mb
也是一元值。
如果以上是正确的,那么Option
Scala 中的二进制操作是什么?例如,什么可以*
在Some(1) * Some(2)
?
我认为orElse
是一个有效的关联二元运算符:
def test(a: Option[Int], b: Option[Int], c: Option[Int]): Boolean =
((a orElse b) orElse c) == (a orElse (b orElse c))
Seq(Option(1), Option(2), None).permutations.forall {
case Seq(a, b, c) => test(a, b, c)
}
这成立。我在 FingerTree 实现中使用了这个属性,它是由 Hinze & Paterson 在他们的 Haskell 版本中提出的,它用于实现区间树。
AnOption
本身不是幺半群,就像 an 本身不是幺半群一样Integer
。幺半群是一种类型 AND 关联二元运算。
您可以将整数类型和加法视为一个幺半群。整数和乘法也是一个幺半群。将两个Integer
s 转换为String
并连接它们 ("2" + "3" = "23") 也是一个有效的关联操作,它可以创建一个带有整数的幺半群:实际上("2" concat "3") concat "4"
= "2" concat ("3" concat "4"
) = "234"。
问题是,由您来定义完成类型的“monoid”定义的关联操作,因此您的问题“什么是关联操作......”的格式不正确。
与整数一样,Option[Int]
加法或乘法可以是幺半群,但Option[Int]
本身不是。
就像@senia 在他的回答中所做的那样,您可以说“如果 T 本身就是一个 Monoid,我可以根据 Option[T] 定义一个幺半群”。在这种情况下,关联操作可以使用为 T 定义的并且Some[a] append Some[b]
可以是Some[a append b]
。
或者,就像@0__ 所做的那样,您可以找到一个特定的操作 ( orElse
),它与Option[Int]
构成一个幺半群。这也是正确的(但请注意答案如何以“orElse 是有效的关联二元运算符”开头)。
其实并不是。Monad
forOption
不是Monoid
for Option[T]
。Monad
为M[_]
和Monoid
为 定义T
。
如果你有这样Monoid
的,你可以创建:Option[T]
Monoid
T
def optionMonoid[T: Monoid]: Monoid[Option[T]] = new Monoid {
def zero: Option[T] = None
def append(f1: Option[T], f2: => Option[T]): Option[T] = (fi, f2) match {
case (None, None) => None
case (Some(a), Some(b)) => Some(a |+| b)
case (r @ Some(_), None) => r
case (None, r @ Some(_)) => r
}
}
幺半群有两种不同的含义。单子是范畴论意义上的幺半群对象(见最后一个例子);它不是抽象代数意义上的幺半群(大多数其他答案都在谈论)。