2012-11-20 9 views
7

Ich habe ein paar Funktionen, deren einzige Parameter Anforderung ist, dass es eine Art von Sammlung, die auch growable (dh es könnte eine Warteschlange, Liste, PriorityQueue, etc.) sein könnte, also versuchte ich erstellen Sie die folgende Art alias:Scala rekursive Art Alias-Fehler

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

wie so mit Funktionsdefinitionen zu verwenden:

def apply(frontier: Frontier) = ??? 

aber die Art Alias ​​gibt den Fehler "Illegal zyklische Referenz Einbeziehung Typ Frontier." Gibt es eine Möglichkeit, die illegale zyklische Referenz zu umgehen, um den Typalias oder etwas Ähnliches zu verwenden?

Eine Lösung ist die folgende verwenden:

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

aber dieses scheint hinzufügen unnötige Ausführlichkeit, wenn die Funktionsdefinition scheinbar genau wie die Art alias gleiche tun wird. Der Typ wird auch an anderen Stellen verwendet, so dass ein Typalias die Lesbarkeit stark erhöht.

Antwort

6

Aus Abschnitt 4.3 von the spec:

Die Bereichsregeln für Definitionen (§ 4) und Typ-Parameter (§4.6) machen es möglich, dass ein Typname in seinem eigenen gebunden oder in seinem rechts erscheint -handseite. Es handelt sich jedoch um einen statischen Fehler, wenn ein Typalias rekursiv auf den definierten Typkonstruktor verweist ( ).

Also nein, es gibt keine Möglichkeit, dies direkt zu tun, aber Sie können mit einem Typ-Parameter vom Typ alias viel das Gleiche erreichen:

type Frontier[F <: Frontier[F]] = Growable[Int] with TraversableLike[Int, F] 

Jetzt einfach schreiben Sie Ihre apply wie folgt aus:

Noch ein wenig weniger wortreich als Ihre hypothetische erste Version, aber kürzer als das ganze Ding zu schreiben.

Sie könnten auch die Wildcard Abkürzung für eine existenzielle Art verwenden nur:

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

nun Ihre erste applywird Arbeit, wie es ist. Sie sagen nur, dass es einige Art geben muss, die diesen Schlitz passt, aber Sie interessieren sich nicht, was es ist.

In diesem Fall speziell, gibt es einen Grund, warum Sie nicht Traversable[Node] stattdessen verwenden? Es würde praktisch das Gleiche erreichen und ist nicht auf seinen Darstellungstyp parametrisiert.

+0

Die erste Lösung ist, was ich gesucht habe. Der Grund, warum ich diesen Typ brauchte, ist im Grunde der Parameter kann jede Sammlung sein, die ich hinzufügen kann (daher Growable), und der Rückgabetyp vieler der Funktionen in Traversable [Node] wäre nur Traversable [Node] im Gegensatz zu Traversable [ Knoten] mit Growable [Node]. Insbesondere verwende ich die Operationen '+ =', 'head',' tail', 'find' und' filterNot'. Es ist möglich, dass ich das Problem neu formulieren könnte, um "+ =" nicht zu benötigen und somit Growable nicht zu benötigen, aber ich habe diese Möglichkeit noch nicht erforscht. –

+0

Wie deklarieren Sie einen Typ, der Frontier ist? – user1453345

Verwandte Themen