4
scala> val a = Need(20)
a: scalaz.Name[Int] = scalaz.Name$$anon$2@173f990

scala> val b = Need(3)
b: scalaz.Name[Int] = scalaz.Name$$anon$2@35201f

scala> for(a0 <- a; b0 <- b) yield a0 + b0
res90: scalaz.Name[Int] = scalaz.Name$$anon$2@16f7209

scala> (a |@| b)
res91: scalaz.ApplicativeBuilder[scalaz.Name,Int,Int] = scalaz.ApplicativeBuilde
r@11219ec

scala> (a |@| b) { _ + _ }
<console>:19: error: ambiguous implicit values:
 both method FunctorBindApply in class ApplyLow of type [Z[_]](implicit t: scala
z.Functor[Z], implicit b: scalaz.Bind[Z])scalaz.Apply[Z]
 and value nameMonad in object Name of type => scalaz.Monad[scalaz.Name]
 match expected type scalaz.Apply[scalaz.Name]
       (a |@| b) { _ + _ }
                 ^

Name是一个Monad,因此Applicative也是一个。为什么这段代码不起作用?我是否需要添加任何类型注释才能使其工作?谢谢!

4

1 回答 1

9

只是部分答案,我对scalaz不太熟悉。(a |@| b)是一个ApplicativeBuilder[Name, Int, Int]。您的调用apply(plus: (Int, Int) => Int)需要两个隐式参数,aFunctor[Name]和 an Apply[Name](略小于Applicative,没有纯参数)。

第二个有问题。正如Name在 type 中出现的那样Apply[Name],同伴object Name被认为是隐式范围,因此隐式val nameMonad: Monad[Name]在隐式范围内。作为Monadextends Applicativewhich extends Apply,它是隐式参数的可能候选者。

但正如它的同伴对象中Apply出现的那样,同伴也被考虑在内。在它的祖先中,有一个Apply[Name]Applyobject ApplyApplyLow

implicit def FunctorBindApply[Z[_]](implicit t: Functor[Z], b: Bind[Z]): Apply[Z] 

Functor[Name]和的实例Bind[Name]存在于隐式范围内(nameMonad 两者都是),因此也FunctorBindApply提供了一个候选Apply对象(它的行为与 nameMonad 完全一样,因为它完全基于它,但它仍然是另一个候选对象)。

我不认为我真的了解优先级规则。定义 inApplyLow而不是Apply会降低相对于伴随对象中定义的东西的优先级Apply。但与在无关对象中定义的东西无关Name。我不认为Monad成为一个子类型Apply可以使它更具体。而且我认为没有其他规则可以在两者之间做出决定,但我必须承认我在这方面有点不知所措。编译器错误消息当然同意它可以在备选方案之间进行选择。

不确定正确的解决方案应该是什么,但nameMonad直接在范围内,例如import Name._ 应该优先考虑。

于 2011-09-16T17:04:55.397 回答