1

我一直在尝试学习更多 Scala 并遇到了这篇讨论 F 有界类型的有趣文章。我对关于使用此类类型的值集合的最终讨论特别感兴趣。

一个简单的例子如下:

abstract class AbsClass[A <: AbsClass[_]] {
  this: A =>
  def me: A = this
}

def me2[A <: AbsClass[A]](a: A): A = a

case class C1(v: Int) extends AbsClass[C1] 
case class C2(v: Int) extends AbsClass[C2] 

如博客文章所示,我们可以使用存在量词来允许我们me2调用C1C2

scala> List[A forSome {type A <: AbsClass[A] }](C1(1), C2(2)).map(me2(_))
res2: List[A forSome { type A <: AbsClass[A] }] = List(C1(1), C2(2))

现在,我一直在尝试对列表类型进行几种变体,我希望有更多经验的人能指出我遗漏的一些细微之处。

以下工作符合我的预期

scala> val l2  =  List[A forSome {type A <: AbsClass[A] }](C1(1), C2(2))
l2: List[A forSome { type A <: AbsClass[A] }] = List(C1(1), C2(2))

scala> l2.map(_.me)
res4: List[A forSome { type A <: AbsClass[A] }] = List(C1(1), C2(2))

我也可以调用_.me并将列表表示为包含 的实例AbsClass[A] forSome {type A},如

scala> val l: List[AbsClass[_]] = List(C1(1), C2(2)).map(_.me)
l: List[AbsClass[_]] = List(C1(1), C2(2))

但是当我尝试再次应用相同的地图l时,我会丢失类型信息并卡在List[Any]. 有没有办法在这里维护类型?

4

1 回答 1

1

请记住,下划线是类型绑定。

val l: List[AbsClass[_]] = List(C1(1), C2(2)).map(_.me)

val ll: List[AbsClass[_ >: Nothing <: Any]] = List(C1(1), C2(2)).map(_.me)

这两件事是一样的。下划线将压缩到 Nothing 的下限或 Any 的上限。

有关存在类型如何工作的更多信息,请参阅:https ://youtu.be/NFnsFda82Yo

于 2016-07-05T04:33:54.457 回答