为什么我需要一个明确的证据类型/为什么这个Scala类型绑定失败?

时间:2011-12-12 09:27:38

标签: scala

下面,第一个案例成功,第二个案例失败。为什么我需要一个明确的证据类型/为什么这个Scala类型绑定失败?在解决A时,类型推断器的特殊限制是什么?

scala> implicit def view[A, C](xs: C)(implicit ev: C <:< Iterable[A]) = new { def bar = 0 } 
view: [A, C](xs: C)(implicit ev: <:<[C,scala.collection.immutable.Iterable[A]])java.lang.Object{def bar: Int}

scala> view(List(1)) bar
res37: Int = 0

scala> implicit def view[A, C <: Seq[A]](xs: C) = new { def bar = 0 } 
view: [A, C <: scala.collection.immutable.Seq[A]](xs: C)java.lang.Object{def bar: Int}

scala> view(List(1)) bar
<console>:149: error: inferred type arguments [Nothing,List[Int]] do not conform to method view's type parameter bounds [A,C <: scala.collection.immutable.Seq[A]]
              view(List(1)) bar
              ^

2 个答案:

答案 0 :(得分:9)

遗憾的是,类型推断不能很好地处理由相同类型参数列表(此处为A)中的(包含)其他类型参数的类型限制的类型参数(例如C)。

使用隐式参数对约束进行编码的版本不会受到此限制,因为implicits施加的约束与类型参数边界强加的约束分开解决。

您还可以通过将xs的类型拆分为在集合(CC)上抽象的类型构造函数和在其元素上抽象的(正确)类型(A)来避免循环,如下所示:

scala> implicit def view[A, CC[x] <: Seq[x]](xs: CC[A]) = new { def bar = 0 } 
view: [A, CC[x] <: Seq[x]](xs: CC[A])Object{def bar: Int}

scala> view(List(1)) bar
res0: Int = 0

有关CC等类型的详细信息,请参阅What is a higher kinded type in Scala?

答案 1 :(得分:1)

我真的不知道为什么会发生这种情况,虽然我的预感是它与Seq的类型参数的方差有关。不过,我可以得到以下工作:

implicit def view[A, C[~] <: Seq[~] forSome { type ~ }](xs: C[A]) = 
   new { def bar = 0 } 

你有没有理由要C - 我的意思是,你打算在方法中使用C吗?因为如果没有,为什么不呢

implicit def view[A](xs: Seq[A]) = new { def bar = 0 }