具有F-bound类型的集合上的函数应用程序

时间:2016-07-05 02:43:26

标签: scala polymorphism f-bounded-polymorphism

我一直在努力学习更多Scala并遇到this interesting article讨论F-bounded类型。关于使用这些类型的值集合进行最后讨论,我特别感兴趣。

一个简单的例子如下:

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] 

如博文中所示,我们可以使用存在量词来允许我们在me2C1

列表上调用C2
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]困住了。有没有办法在这里维护类型?

1 个答案:

答案 0 :(得分: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