Scala 递归类型别名错误

标签 scala types

我有几个函数,其唯一的参数要求是它具有某种可增长的集合(即它可以是队列、列表、优先级队列等),因此我尝试创建以下类型别名:

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/

相关文章:

scala - 使用 Spark Dataframe 中的函数创建新列

typescript - 如何根据字段值省略联合类型

types - 您能否在 F# 中为函数指定特定的类型签名?

Scala 不处理 ':' 函数的非显式类型闭包

c# - 在 C# 中使用相同布局强制不同命名空间中的类型

scala - 在 Scala 中尝试 Haskell 风格的惰性求值时出现堆栈溢出错误

scala - 通用 "nested members"特征

scala - 从字符串文字推断 Spark DataType

multithreading - Akka 中使用 Actor 模型的读写器锁

postgresql - 使用 play-slick 时与 heroku postgres 的间歇性连接失败