【问题标题】:Scala Monoid Combinator for Options用于选项的 Scala Monoid 组合器
【发布时间】:2017-04-20 10:25:04
【问题描述】:

假设我有一个 Monoid 特征,如下所示:

trait Monoid[A] {
  def combine(a1: A, a2: A): A
  def identity: A
}

现在如果我想为此写一个 optionMonoid,我可以这样写:

val optionMonoid1 = new Monoid[Option[A]] {
  def combine(a1: Option[A], a2: Option[A2]) a1 orElse a2
  def identity = None
}

这是因为我对 Option 中的内部类型一无所知。但是,如果我想以一种我想真正组合 Option 中的内部类型的方式使用 combine 运算符呢?

【问题讨论】:

  • 如果你想map 覆盖Option 中的值,你需要一个 Functor 实例。
  • 但是等等,Functor 实例不会改变我包含在 Option 中的类型吗?
  • 即使我有一个 Functor 实例,我仍然不知道我的 A 是什么类型,因此我可以在我的类型 A 上应用组合运算符!
  • 您已经可以利用 Option 是一个 Functor 并且具有 map 函数这一事实。但是结合两个选项的真正含义是什么?您正在组合两个容器,它们可能包含也可能不包含值。你需要的是类型 A 有一个 Monoid 实例,这样你就可以在内部组合这些 As。

标签: scala monoids


【解决方案1】:

一个选项:

trait Semigroup[A] {
  def combine(a1: A, a2: A): A
}

trait Monoid[A] extends Semigroup[A] {
  def identity: A
}

def optionMonoid2[A](implicit sgA: Semigroup[A]) = new Monoid[Option[A]] {
  def combine(a1: Option[A], a2: Option[A2]) = (a1, a2) match {
    case (Some(b1), Some(b2)) => Some(sgA.combine(b1, b2))
    case _ => a1.orElse(a2)
  }
  def identity = None
}

很容易验证幺半群定律成立。

【讨论】:

  • def identity = None Some 的情况如何?
  • 因此,comine 运算符适用于范围内可见的任何 Semigroup 实例!°
  • @sparkr 正如我在上面评论的那样。您需要包含在框内的类型 (A) 也具有幺半群属性。
  • 酷!感谢您的帮助!
  • @YuvalItzchakov 因为对于所有x: AoptionMonoid2.combine(Some(x), None) == Some(x).orElse(None) == Some(x)optionMonoid2.combine(None, Some(x)) == None.orElse(Some(x)) == Some(x)
猜你喜欢
  • 2020-04-14
  • 2012-04-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-20
  • 1970-01-01
相关资源
最近更新 更多