下面,第一个案例成功,第二个案例失败。为什么我需要一个明确的证据类型/为什么这个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
^
答案 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 }