基于返回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)当然,所有这些行为只是编译器的微妙之处,我不认为这样的部分情况确实需要深刻的理解。