繁体   English   中英

存在类型和类型成员

[英]Existential types and type members

什么有效(A部分​​)

假设我有一个带有类型参数的特征:

trait A[T]

我可以使用存在类型来编写一个方法,该方法将采用所有具有相同TA的集合:

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 }

我可以编写一个只带有一些指定TB的方法:

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

但这实际上并不起作用 - 你得到了与上面简化例子中相同的奇怪结果。

我终于解决了(至少我希望如此)。 让我们以另一种方式做。 我们建立我们的特质:

scala> trait B {type T}
defined trait B

我们尝试构建一个B序列:

scala> Seq(new B {type T = Int}, new B {type T = String})
res0: Seq[B{type T >: String with Int}] = List($anon$1@592b12d, $anon$2@61ae0436)

该死的,它的作品! 好吧,我们没有type T的相等,但让我们玩它:

scala> res0 : (Seq[B {type T = X}] forSome {type X >: String with Int})
res1: Seq[B{type T = X}] forSome { type X >: String with Int } = List($anon$1@592b12d, $anon$2@61ae0436)

它更接近了。 没有等待,它不是更接近,它比你提出的baz参数更好 ,我们不仅提供原始类型,我们也有一个上限! 因此,我们可以清楚地将它传递给baz 这就是它无法按预期工作的原因。

在你的例子中:

scala> def baz(bs: Seq[B { type T = X }] forSome { type X }) = true

告诉编译器函数baz采用特征B的Seq。 特征B碰巧采用类型成员T,但就编译器而言,即使B类型成员T的类型不相同,函数baz也可以采用特征B的Seq。 如果你想让函数baz采用具有相同类型成员的特征B的Seq,你需要告诉编译器如下:

scala> def baz[X](bs: Seq[B { type T = X }]) = true
baz: [X](bs: Seq[B{type T = X}])Boolean


scala> baz[Int](Seq(new B { type T = Int }, new B { type T = String }))
    <console>:10: error: type mismatch;
    found   : java.lang.Object with B
    required: B{type T = Int}
              baz[Int](Seq(new B { type T = Int }, new B { type T = String }))
                                               ^

scala> baz[Int](Seq(new B { type T = Int }, new B { type T = Int }))
res10: Boolean = true

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM