Ich möchte Objektinstanzen als Module/functors verwenden, mehr oder weniger, wie unten dargestellt:Wie benutzt man Objekte als Module/Funktoren in Scala?
abstract class Lattice[E] extends Set[E] {
val minimum: E
val maximum: E
def meet(x: E, y: E): E
def join(x: E, y: E): E
def neg(x: E): E
}
class Calculus[E](val lat: Lattice[E]) {
abstract class Expr
case class Var(name: String) extends Expr {...}
case class Val(value: E) extends Expr {...}
case class Neg(e1: Expr) extends Expr {...}
case class Cnj(e1: Expr, e2: Expr) extends Expr {...}
case class Dsj(e1: Expr, e2: Expr) extends Expr {...}
}
, dass ich für jedes Gitter eine andere Kalkül Instanz erstellen können also (die Operationen Ich brauche die Informationen, von denen durchführen wird sind die maximalen und minimalen Werte des Gitters). Ich möchte in der Lage sein, Ausdrücke desselben Kalküls zu mischen, aber Ausdrücke verschiedener Ausdrücke nicht mischen zu dürfen. So weit, ist es gut. Ich kann meine Kalkülinstanzen erstellen, aber das Problem ist, dass ich keine Funktionen in anderen Klassen schreiben kann, die sie manipulieren.
Zum Beispiel versuche ich einen Parser zu erstellen, um Ausdrücke aus einer Datei zu lesen und sie zurückzugeben; Ich habe auch versucht, einen Zufallsgenerator zu schreiben, um ihn in meinen Tests mit ScalaCheck zu verwenden. Es stellt sich heraus, dass jedes Mal, wenn eine Funktion ein Expr-Objekt generiert, ich es nicht außerhalb der Funktion verwenden kann. Auch wenn ich die Calculus-Instanz erzeuge und sie als Argument an die Funktion übergebe, die ihrerseits die Expr-Objekte generiert, wird die Rückgabe der Funktion nicht als vom selben Typ der außerhalb der Funktion erzeugten Objekte erkannt.
Vielleicht ist mein Englisch nicht klar genug, lassen Sie mich ein Spielzeugbeispiel von dem versuchen, was ich tun möchte (nicht der echte ScalaCheck Generator, aber nahe genug).
def genRndExpr[E](c: Calculus[E], level: Int): Calculus[E]#Expr = {
if (level > MAX_LEVEL) {
val select = util.Random.nextInt(2)
select match {
case 0 => genRndVar(c)
case 1 => genRndVal(c)
}
}
else {
val select = util.Random.nextInt(3)
select match {
case 0 => new c.Neg(genRndExpr(c, level+1))
case 1 => new c.Dsj(genRndExpr(c, level+1), genRndExpr(c, level+1))
case 2 => new c.Cnj(genRndExpr(c, level+1), genRndExpr(c, level+1))
}
}
}
Nun, wenn ich versuche, den obigen Code ich viele
error: type mismatch; found : plg.mvfml.Calculus[E]#Expr required: c.Expr case 0 => new c.Neg(genRndExpr(c, level+1))
zu kompilieren Und das gleiche passiert, wenn ich versuche, wie etwas zu tun:
val boolCalc = new Calculus(Bool)
val e1: boolCalc.Expr = genRndExpr(boolCalc)
Bitte beachten Sie, dass Der Generator selbst ist nicht von Belang, aber ich muss viel Ähnliches tun (dh Kalkulationsexemplarausdrücke erstellen und bearbeiten), was den Rest des Systems betrifft.
Mache ich etwas falsch? Ist es möglich zu tun, was ich tun möchte?
Hilfe zu diesem Thema wird dringend benötigt und geschätzt. Vielen Dank im Voraus.
Nach Erhalt einer Antwort von Apocalisp und versuchen es.
Vielen Dank für die Antwort, aber es gibt immer noch einige Probleme. Die vorgeschlagene Lösung war die Signatur der Funktion zu ändern:
def genRndExpr[E, C <: Calculus[E]](c: C, level: Int): C#Expr
ich die Unterschrift für alle Funktionen geändert beteiligt: getRndExpr, getRndVal und getRndVar.Und ich habe die gleiche Fehlermeldung überall, wo ich diese Funktionen aufrufen und bekam die folgende Fehlermeldung:
error: inferred type arguments [Nothing,C] do not conform to method genRndVar's type parameter bounds [E,C <: plg.mvfml.Calculus[E]] case 0 => genRndVar(c)
Da der Compiler schien nicht in der Lage zu sein, die richtigen Typen, um herauszufinden, ich alle Funktionsaufruf geändert wie unten sein:
case 0 => new c.Neg(genRndExpr[E,C](c, level+1))
Danach wird auf den ersten 2 Funktionsaufrufe (genRndVal und genRndVar) gab es keine Kompilierung Fehler, sondern auf den folgenden 3 Anrufe (rekursive Aufrufe zu genRndExpr), wobei die Rückkehr der Funktion verwendet wird, ein bauen neues Expr-Objekt Ich habe folgende Fehlermeldung erhalten:
error: type mismatch; found : C#Expr required: c.Expr case 0 => new c.Neg(genRndExpr[E,C](c, level+1))
Also, wieder, ich stecke fest. Jede Hilfe wird geschätzt.
Ihr Fragetitel ist ein bisschen irreführend. Betrachten Sie etwas wie "Wie bezieht man innere Klassen von expernal relativ zum Klassenraum?" – Alexey