Как использовать Имя в качестве аппликативного? - PullRequest
4 голосов
/ 16 сентября 2011
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 тоже. Почему этот код не работает тогда? Нужно ли размещать какие-либо аннотации типа, чтобы это работало? Спасибо!

1 Ответ

9 голосов
/ 16 сентября 2011

Просто частичный ответ, я не слишком знаком со скалазом.(a |@| b) является ApplicativeBuilder[Name, Int, Int].Ваш вызов apply(plus: (Int, Int) => Int) требует два неявных параметра: Functor[Name] и Apply[Name] (чуть меньше Applicative, чистых нет).

Проблема со вторым.Поскольку Name появляется в типе Apply[Name], спутник object Name рассматривается для неявной области, и поэтому неявная val nameMonad: Monad[Name] находится в неявной области.Поскольку Monad расширяет Applicative, что расширяет Apply, это возможный кандидат для неявного параметра.

Но так как Apply появляется в Apply[Name], его сопутствующий объект Apply, считается также спутник object Apply.И в его предке ApplyLow есть

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

Экземпляры Functor[Name] и Bind[Name] присутствуют в неявной области видимости (nameMonad - оба), поэтому FunctorBindApply предоставляет кандидата Apply тоже (который будет вести себя точно так же, как nameMonad, поскольку он полностью основан на нем, но, тем не менее, это еще один кандидат).

Не думаю, что я действительно понимаю правила приоритета.Наличие определения в ApplyLow вместо Apply уменьшит приоритет относительно чего-то определенного в сопутствующем объекте Apply.Но не относительно чего-то определенного в неродственном объекте Name.Я не думаю, что Monad как подтип Apply считается более конкретным.И я не вижу другого правила, которое могло бы решить между ними, но я должен признаться, что я немного растерялся.Сообщения об ошибках компилятора, безусловно, согласны с тем, что он может выбирать между альтернативами.

Не уверен, какое должно быть правильное решение, но приоритет должен иметь nameMonad, например, с import Name._.

...