Ich würde gerne wissen, wie die Mitgliedstypen in Scala arbeiten, und wie ich Typen zuordnen soll.Typ Parameter im Vergleich zu Mitgliedstypen in Scala
Ein Ansatz besteht darin, den zugeordneten Typ zu einem Typparameter zu machen. Der Vorteil dieses Ansatzes ist, dass ich die Varianz des Typs vorschreiben kann, und ich kann sicher sein, dass ein Subtyp den Typ nicht ändert. Die Nachteile sind, dass ich den Typparameter nicht vom Typ in einer Funktion ableiten kann. Der zweite Ansatz besteht darin, den zugeordneten Typ zu einem Mitglied des zweiten Typs zu machen, was das Problem hat, dass ich keine Grenzen für die zugeordneten Typen der Subtypen vorschreiben kann und daher den Typ in den Funktionsparametern nicht verwenden kann (wenn x: x, x # T möglicherweise nicht in jeder Beziehung mit xT)
ein konkretes Beispiel wäre:
ich ein Merkmal für DFAs haben (ohne den Typ-Parameter sein könnte)
trait DFA[S] { /* S is the type of the symbols in the alphabet */
trait State { def next(x : S); }
/* final type Sigma = S */
}
und ich möchte eine Funktion zum Ausführen erstellen diese DFA über eine Eingangssequenz, und ich möchte
- die Funktion etwas
<% Seq[alphabet-type-of-the-dfa]
als Eingangssequenz Typen festgelegt werden - die Funktion Anrufer müssen die Art Parameter nicht angeben, müssen alle
- gefolgert werden, würde ich wie die Funktion, die mit dem konkreten DFA-Typ aufgerufen werden soll (aber wenn es eine Lösung gibt, bei der die Funktion keinen Typparameter für das DFA haben würde, ist es in Ordnung)
- Die Alphabettypen müssen unbeschränkt sein (d. muss diese als auch für eine noch unbekannte benutzerdefinierte Klasse)
- die DFAs mit unterschiedlichen Alphabet-Typen sind nicht Subtypen
Ich hat versucht, ein DFA für Char sein:
def runDFA[S, D <: DFA[S], SQ <% Seq[S]](d : D)(seq : SQ) = ....
dieser Werke , außer der Typ S wird hier nicht abgeleitet, daher muss ich die gesamte Typenparameterliste auf jeder Aufrufseite schreiben.
def runDFA[D <: DFA[S] forSome { type S }, SQ <% Seq[D#Sigma]](... same as above
dies nicht funktioniert hat (ungültige zirkuläre Referenz D eingeben ??? (was ist das?))
ich auch den Typ Parameter gelöscht, erstellt eine abstrakte Art Sigma und versuchte, diese Art Bindung in den konkreten Klassen. runDFA würde aussehen wie
def runDFA[D <: DFA, SQ <% Seq[D#Sigma]](... same as above
aber dies führt unweigerlich zu Problemen wie "type mismatch: expected dfa.Sigma
, bekam D#Sigma
"
Irgendwelche Ideen? Zeiger?
Edit:
Da die Antworten zeigen, gibt es keine einfache Möglichkeit, dies zu tun, könnte jemand mehr erarbeiten, warum ist es nicht möglich, und was geändert werden müssen, damit es funktioniert?
Die Gründe, warum ich runDFA ro eine freie Funktion (keine Methode) sein möchte, ist, dass ich andere ähnliche Funktionen, wie Automatenminimierung, reguläre Sprachoperationen, NFA-zu-DFA-Konvertierungen, Sprachfaktorisierung etc. und alle haben möchte Dies innerhalb einer Klasse ist gegen fast jedes Prinzip des OO-Designs.
Wow, ich dachte du meintest das: http://www.huygens-fokker.org/scala/ – MusiGenesis