给定一个类型类,其中应根据返回类型执行实例选择:
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)无法解析正确的实例:
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]
^
当使用隐式函数时根据返回类型找到隐式没有问题(我们在此将其重新定义为 i 以说明它与 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中类型类的便利性。
编辑:我正在研究如何在不进行类型推断的情况下实现这一目标。否则,我想了解为什么那是不可能的。如果将此限制记录为Scala问题,我找不到它。答案 0 :(得分:1)
1)按如下方式重写代码后:
def mzero[A]()(implicit m: Monoid[_ <: A]) : A = m.m0
然后变得清楚为什么这样做。
2)在必须将mzero设置为def mzero[A <: B, B]()(implicit m: Monoid[A]) : A = m.m0
之后,您启用了其他类型推断来解析存在类型。编译器从所需的返回类型获得实际类型。
如果需要,可以使用{{1}}进行检查。
3)当然,所有这些行为都只是编译器的微妙之处,我认为这种局部案例并不需要深入理解。