基于返回类型

时间:2015-06-01 16:09:44

标签: scala type-inference implicit return-type scalaz

给定一个类型类,其中应根据返回类型执行实例选择:

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问题,我找不到它。

1 个答案:

答案 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)当然,所有这些行为都只是编译器的微妙之处,我认为这种局部案例并不需要深入理解。