为什么scalaz';选项的幺半群的实现对f2函数求值两次?
scalaz选项幺半群的定义如下:为什么scalaz';选项的幺半群的实现对f2函数求值两次?,scala,scalaz,scalaz7,Scala,Scalaz,Scalaz7,scalaz选项幺半群的定义如下: 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
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
可能非常昂贵
我错过什么了吗
在我看来,这篇文章是为了强调问题的对称性,为了清晰,而不是为了速度。您不能仅仅删除第二个参数的惰性,因为
半群
就是这样定义的,在其他上下文中,第二个参数的惰性可能是必不可少的。要保留问题对称性的视觉表示,您可能只需要添加
val g2 = f2 // Force evaluation
(f1, g2) match { ...
或者类似的
(如果可以将按名称命名的参数称为lazy来自动记忆它们,那就太好了。)可能是Haskell思想中的一个遗留问题,在那里等价的定义比较便宜?您测试过吗?在里面放一些println然后检查。是的,我做了测试,println被击中了两次。我想我会修复它并向scalaz提交一个拉请求。我将它作为拉请求提交,他们将其合并,但您的解决方案也会起作用。