函数在有f界类型集合上的应用



我一直在努力学习更多的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] 

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

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]卡住了。有办法保持这里的类型吗?

请记住,下划线是类型约束。

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

相关内容

  • 没有找到相关文章

最新更新