2012-11-20 96 views
7

我有幾個函數,其唯一的參數要求是它有某種集合也是可增長的(即它可能是一個隊列,列表,PriorityQueue等),所以我試圖創建以下類型別名:斯卡拉遞歸類型別名錯誤

type Frontier = Growable[Node] with TraversableLike[Node, Frontier] 

與函數定義使用像這樣:

def apply(frontier: Frontier) = ??? 

但類型別名返回錯誤「非法循環引用涉及類型前沿。」有沒有辦法繞過非法循環引用使用類型別名或類似的東西?

一種解決方案是使用以下命令:

def apply[F <: Growable[Node] with TraversableLike[Node, F]](f: F) = ??? 

但這似乎增加不必要的冗長當函數定義看似在做同樣的事情作爲類型的別名。該類型也用於其他地方,因此類型別名將大大提高可讀性。

回答

6

the spec第4.3節:

的定義範圍規則(§4)和類型參數(§4.6)使 它可能是一個類型的名字出現在自己的約束或在其 權 - 手邊。但是,如果類型別名遞歸引用 到定義的類型構造函數本身,則它是一個靜態錯誤。

因此,沒有,沒有辦法直接做到這一點,但你可以做到同樣的事情與類型別名類型參數:

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, _] 

現在你的第一個apply的工作,因爲它是。你只是說,必須有一些類型,適合那個插槽,但你不在乎它是什麼。

在這種情況下,具體而言,是不是有沒有使用Traversable[Node]的原因呢?它會完成幾乎相同的事情,並且沒有參數化其表示類型。

+0

第一個解決方案就是我一直在尋找的東西。我需要這種類型的原因基本上是參數可以是我可以添加到的任何集合(因此可擴展),並且Traversable [Node]中的許多函數的返回類型將只是Traversable [Node]而不是Traversable [節點]與Growable [節點]。 具體來說,我使用的是操作'+ =','head','tail','find'和'filterNot'。有可能我可以重新解釋問題,不需要'+ =',因此不需要Growable,但我還沒有探索過這個途徑。 –

+0

你如何聲明一個Frontier類型? – user1453345