我有几个函数,其唯一的参数要求是它具有某种可增长的集合(即它可以是队列、列表、优先级队列等),因此我尝试创建以下类型别名:
type Frontier = Growable[Node] with TraversableLike[Node, Frontier]
与函数定义一起使用,如下所示:
def apply(frontier: Frontier) = ???
但类型别名返回错误“涉及类型 Frontier 的非法循环引用”。有没有办法绕过非法循环引用以使用类型别名或类似的东西?
一种解决方案是使用以下内容:
def apply[F <: Growable[Node] with TraversableLike[Node, F]](f: F) = ???
但是当函数定义看起来与类型别名执行完全相同的操作时,这似乎会增加不必要的冗长。该类型也在其他地方使用,因此类型别名会大大提高可读性。
最佳答案
摘自 the spec 的第 4.3 节:
The scope rules for definitions (§4) and type parameters (§4.6) make it possible that a type name appears in its own bound or in its right-hand side. However, it is a static error if a type alias refers recursively to the defined type constructor itself.
所以不,没有办法直接执行此操作,但您可以使用类型别名上的类型参数来完成几乎相同的操作:
type Frontier[F <: Frontier[F]] = Growable[Int] with TraversableLike[Int, F]
现在你只需编写你的apply
,如下所示:
def apply[F < Frontier[F]](frontier: F) = ???
仍然比假设的第一个版本更冗长,但比写出整个内容要短。
您也可以仅使用通配符简写来表示存在类型:
type Frontier = Growable[Node] with TraversableLike[Node, _]
现在您的第一个申请
将按原样工作。您只是说必须有某种类型适合该插槽,但您并不关心它是什么。
但是,在这种情况下,您是否有理由不使用 Traversable[Node]
来代替?它实际上可以完成相同的事情,并且不会对其表示类型进行参数化。
关于Scala 递归类型别名错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13483076/