How do I use Name as an applicative?

ぐ巨炮叔叔 提交于 2019-12-23 13:14:05

问题


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 is an Monad, therefore an Applicative too. Why doesn't this code work then? Do I need to put any type annotations to make it work? Thanks!


回答1:


Just a partial answer, I'm not too familiar with scalaz. (a |@| b) is an ApplicativeBuilder[Name, Int, Int]. Your call to apply(plus: (Int, Int) => Int) requires two implicit parameter, a Functor[Name] and an Apply[Name] (a little less than Applicative, there is no pure).

There is a problem with the second one. As Name appears in type Apply[Name], companion object Name is considered for implicit scope, and so the implicit val nameMonad: Monad[Name] is in the implicit scope. As Monad extends Applicative which extends Apply, it is a possible candidate for the implicit parameter.

But as Apply appears in Apply[Name] its companion object Apply, companion object Apply is considered too. And in its ancestor ApplyLow, there is an

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

Instances of Functor[Name] and Bind[Name] are present in implicit scope (nameMonad is both of them), so FunctorBindApply provides a candidate Apply too (which would behave exactly as nameMonad as it is completely based on it, but it is another candidate nevertheless).

I don't think I really understand the priority rules. Having definition in ApplyLow rather than Apply would reduce the priority relative to something defined in companion object Apply. But not relative to something defined in unrelated object Name. I don't think Monad being a subtype of Apply counts as making it more specific. And I see no other rule that could decide between the two, but I must confess I'm a little at loss there. The compiler error messages certainly agree it can choose between the alternatives.

Not sure what the right solution should be, but having nameMonad directly in scope, for instance with import Name._ should give it priority.



来源:https://stackoverflow.com/questions/7447591/how-do-i-use-name-as-an-applicative

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!