我想编写一个方法,对值的map的子类型进行操作,以便遍历。我的第一次尝试是将其定义为:
def m[A, B, T[B] <: Traversable[B], M[A, T[B]] <: collection.Map[A, T[B]]](m: M[A, T[B]]): M[A, T[B]]
但是,这个定义给出了以下类型错误:
T[B] takes no type parameters, expected: one
def m[A, B, T[B] <: Traversable[B], M[A, T[B]] <: collection.Map[A, T[B]]](m: M[A, T[B]]): M[A, T[B]] = {
^
和
T[B] takes no type parameters, expected: one
def m[A, B, T[B] <: Traversable[B], M[A, T[B]] <: collection.Map[A, T[B]]](m: M[A, T[B]]): M[A, T[B]] = {
^
我认为T[B] <: Traversable[B]
和M[A, T[B]] <: M[A, T[B]]
的定义没有任何区别,只有一个类型参数级别。
当我使用另一个类型参数M
进行参数化时,我得到了同样的错误:
def m[A, B, C, T[B] <: Traversable[B], M[C, T[C]] <: collection.Map[C, T[C]]](m: M[C, T[C]]): M[C, T[C]]
如果我将签名更改为
def m[A, B, T[B] <: Traversable[B], M <: collection.Map[A, T[B]]](m: M): M
并从M
中删除类型参数,编译错误消失。任何人都可以向我解释第一个版本的问题是什么?
最后一个版本编译,但在调用站点给出类型错误,所以我猜应该以某种方式提供类型参数。例如
val map = mutable.Map.empty[Int, Set[Int]]
m(map)
给出
inferred type arguments [Nothing,Nothing,Nothing,scala.collection.mutable.Map[Int,Set[Int]]] do not conform to method m's type parameter bounds [A,B,T[B] <: Traversable[B],M <: scala.collection.Map[A,T[B]]]
m(map)
^
答案 0 :(得分:3)
类似T[B] <: Traverable[B]
的绑定类型不应引用其他类型参数。相反,B
意味着“自由”参数。您应该将其替换为其他符号,例如T[X] <: Traverable[X]
。您也不需要完全要求M[A, T[B]] <: Map[A, T[B]]
,因为T[B]
已经绑定在其他位置。您可以将其替换为M[Y, Z] <: Map[Y, Z]
。
def m[A, B, T[X] <: Traversable[X], M[Y, Z] <: collection.Map[Y, Z]](m: M[A, T[B]]): M[A, T[B]] = m
scala> m(collection.mutable.Map.empty[Int, Set[Int]])
res6: scala.collection.mutable.Map[Int,Set[Int]] = Map() // correctly inferred
scala> m(collection.mutable.Map.empty[Int, Int]) // fails to conform
<console>:12: error: no type parameters for method m: (m: M[A,T[B]])M[A,T[B]] exist so that it can be applied to arguments (scala.collection.mutable.Map[Int,Int])