2

我记得monad是一个monoid。也就是说,有一个关联二元运算 *,因此如果mamb一元值,那么ma * mb也是一元值。

如果以上是正确的,那么OptionScala 中的二进制操作是什么?例如,什么可以*Some(1) * Some(2)

4

5 回答 5

4
于 2014-02-17T13:25:36.643 回答
4

我认为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 版本中提出的,它用于实现区间树。

于 2014-02-17T11:54:35.467 回答
3

AnOption本身不是幺半群,就像 an 本身不是幺半群一样Integer。幺半群是一种类型 AND 关联二元运算。

您可以将整数类型和加法视为一个幺半群。整数和乘法也是一个幺半群。将两个Integers 转换为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 是有效的关联二元运算符”开头)。

于 2014-02-17T11:48:38.567 回答
2

其实并不是。MonadforOption不是Monoidfor Option[T]MonadM[_]Monoid为 定义T

如果你有这样Monoid的,你可以创建:Option[T]MonoidT

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
  }
}
于 2014-02-17T11:00:31.093 回答
2

幺半群有两种不同的含义。单子是范畴论意义上的幺半群对象(见最后一个例子);它不是抽象代数意义上的幺半群(大多数其他答案都在谈论)。

于 2014-02-17T14:00:10.737 回答