为什么scalaz实现Monoid for Option会两次评估f2函数?

时间:2013-05-02 19:26:31

标签: scala scalaz scalaz7

scalaz选项monoid的定义如下:

implicit def optionMonoid[A: Semigroup]: Monoid[Option[A]] = new Monoid[Option[A]] {
  def append(f1: Option[A], f2: => Option[A]) = (f1, f2) match {
    case (Some(a1), Some(a2)) => Some(Semigroup[A].append(a1, a2))
    case (Some(a1), None)     => f1
    case (None, Some(a2))     => f2
    case (None, None)         => None
  }

  def zero: Option[A] = None
}

f2是名称参数传递,这意味着每个调用都将评估表达式。为什么要在模式匹配中进行评估时再次进行评估?返回Some(a2)应该是相同的结果,表达式f2可能非常昂贵。

我错过了什么吗?

Scalaz's Option.scala source

1 个答案:

答案 0 :(得分:4)

在我看来,它的目的是为了突出问题的对称性和清晰度,而不是速度。你不能放弃第二个参数的懒惰,因为Semigroup以这种方式定义,而在其他情况下,第二个参数的懒惰可能是必不可少的。要保留问题对称性的直观表示,您可能只想添加

val g2 = f2  // Force evaluation
(f1, g2) match { ...

或某些。

(如果名称参数可以被称为懒惰以自动记忆它们,那将是很好的。)