什么有效(A部分)
假设我有一个带有类型参数的特征:
trait A[T]
我可以使用存在类型来编写一个方法,该方法将采用A
所有具有相同的 s的集合T
:
def foo(as: Seq[A[X]] forSome { type X }) = true
请注意,这与以下内容不同:
def otherFoo(as: Seq[A[X] forSome { type X }]) = true
或等价物:
def otherFoo(as: Seq[A[_]]) = true
在这些情况下,存在的范围在 内Seq
,所以A
s 可以有不同T
的 s。使用我的原件foo
(在 上存在存在范围Seq
),以下内容很好:
foo(Seq(new A[Int] {}, new A[Int] {}))
但是使类型参数不同,它不会编译:
scala> foo(Seq(new A[Int] {}, new A[String] {}))
<console>:10: error: type mismatch;
found : Seq[A[_ >: java.lang.String with Int]]
required: Seq[A[X]] forSome { type X }
foo(Seq(new A[Int] {}, new A[String] {}))
^
这一切都很简单。
什么有效(B部分)
现在假设我有一个类型成员而不是类型参数的类似特征:
trait B { type T }
我可以编写一个只需要B
一些指定的方法T
:
scala> def bar[X](b: B { type T = X }) = true
bar: [X](b: B{type T = X})Boolean
scala> bar[Int](new B { type T = Int })
res5: Boolean = true
scala> bar[String](new B { type T = Int })
<console>:10: error: type mismatch;
found : java.lang.Object with B
required: B{type T = String}
bar[String](new B { type T = Int })
^
同样,这完全符合您的预期。
什么不起作用
当我们尝试编写foo
上面的等价物时,但对于类型成员,事情变得很奇怪。
scala> def baz(bs: Seq[B { type T = X }] forSome { type X }) = true
baz: (as: Seq[B{type T = X}] forSome { type X })Boolean
scala> baz(Seq(new B { type T = Int }, new B { type T = String }))
res7: Boolean = true
最后一行编译对我来说毫无意义。我已经告诉它我希望所有类型成员都相同。我foo
表明我可以对类型参数执行此操作,并bar
表明我可以根据类型成员约束类型。但我不能将两者结合起来。
我在 2.9.2 和 2.10.0-M5 上试过这个。
动机
这个问题的灵感来自这个问题,我的第一个想法是,哦,只需使用存在类型(暂时搁置一个问题,即似乎不可能将存在类型应用于重复参数类型的范围,这在这里很方便):
def accept(rs: Seq[RList[Int] { type S = X }] forSome { type X }) = true
但这实际上不起作用——你会得到与上面简化示例相同的奇怪结果。