基于返回types推理的意外隐式parsing

给定一个typestypes,应根据返回types执行实例select:

case class Monoid[A](m0: A) // We only care about the zero here implicit def s[T] : Monoid[Set[T]] = Monoid(Set.empty[T]) implicit def l[T] : Monoid[List[T]] = Monoid(List.empty[T]) def mzero[A](implicit m: Monoid[A]) : A = m.m0 

为什么Scala(2.11.6)无法parsing正确的实例:

 scala> mzero : List[Int] <console>:24: error: ambiguous implicit values: both method s of type [T]=> Monoid[Set[T]] and method l of type [T]=> Monoid[List[T]] match expected type Monoid[A] mzero : List[Int] ^ 

当使用隐式函数的时候,根据返回typesfind一个隐式就没有问题了(我们在这里重新定义它作为来说明它与mzero的相似程度

 def i[A](implicit a : A) : A = a scala> i : Monoid[List[Int]] res18: Monoid[List[Int]] = Monoid(List()) 

错误信息中的Monoid[A]而不是Monoid[List[Int]]令人费解。

我会假设许多scalaz贡献者对这个问题很熟悉,因为它似乎限制了scala中types类的方便性。

编辑:我正在研究得到这个工作,而不是types推断。 否则我想明白为什么这是不可能的。 如果这个限制被logging为一个Scala问题,我找不到它。

1)重写你的代码如下:

 case class Monoid[A](m0: A) // We only care about the zero here implicit def s[T] : Monoid[Set[T]] = Monoid(Set.empty[T]) implicit def l[T] : Monoid[List[T]] = Monoid(List.empty[T]) def mzero[A]()(implicit m: Monoid[A]) : A = m.m0 val zero = mzero[List[Int]]() val zero2: List[Int] = mzero() 

那么很明显为什么这样工作。

2)必须将mzero设置为def mzero[A]()(implicit m: Monoid[_ <: A]) : A = m.m0之后,启用了附加types推断来parsing存在types。 编译器从所需的返回types获得实际的types。 你可以用def mzero[A <: B, B]()(implicit m: Monoid[A]) : A = m.m0来检查它。

3)当然,所有这些行为只是编译器的微妙之处,我不认为这样的部分情况确实需要深刻的理解。