Hier ist ein Designproblem, das ich wiederholt hatte. Angenommen, Sie erstellen einen Compiler, wie speichern Sie die Typen in den Bäumen?Entwurf von unveränderlichen, typisierbaren Bäumen
eine einfache Expr
und Type
Hierarchie betrachten und davon ausgeht, dass Plus
und Equals
polymorph sind (plus auf booleans in nur ||
, zum Beispiel).
trait Type
case object BoolType extends Type
case object IntType extends Type
case object Untyped extends Type
trait Expr { var tpe : Type = Untyped }
case class Var(id : String) extends Expr
case class Plus(l : Expr, r : Expr) extends Expr
case class Equals(l : Expr, r : Expr) extends Expr
// ...
Nehmen wir weiter an, dass ich die Art von Identifikatoren weiß nicht, wann ich die Ausdrucksbäume konstruieren und damit die Art von Konstruktion nicht wissen kann. nun eine typische Typprüfung Funktion könnte wie folgt aussehen:
def typeCheck(env : Map[String,Type])(expr : Expr) : Expr = expr match {
case Var(id) =>
expr.tpe = env(id)
expr
case Plus(l,r) =>
val tl = typeCheck(env)(l)
val tr = typeCheck(env)(r)
assert(tl == tr)
expr.tpe = tl
expr
// etc.
}
Diese recht einfach ist, zu schreiben, aber kommt mit zwei großen Problemen:
Expr
s wandelbar sind. Niemand mag Mutation.- Typisierte und nicht typisierte Ausdrücke können nicht unterschieden werden. Ich kann keine Funktion schreiben, deren Signatur angibt, dass ihr Argument ein typisierter Ausdruck sein muss.
Also meine Frage ist die folgende. Was ist ein guter Weg (ich nicht Entwurfsmuster sagen wagen) möglicherweise nicht typisierten Bäume zu definieren, so dass:
- ich nur einmal die
Expr
Hierarchie definieren muß. - Getippte und untypisierte Bäume haben unterschiedliche Typen und ich kann wählen, sie inkompatibel zu machen.
Edit: Eine weitere Voraussetzung ist, dass es für Typ-Systeme mit unbeschränkter und unberechenbar Anzahl von Typen funktionieren soll (man denkt: case class ClassType(classID : String) extends Type
, zum Beispiel).
Ein Anwendungsbeispiel wäre großartig. Wie würden Sie "typeCheck" in Ihrem System umschreiben? –
Das sieht so aus, als könnte es sein, wonach ich gesucht habe. Wie Eugene vorschlägt, könnten Sie vielleicht zeigen, wie Sie meine 'typeCheck' Funktion an Ihre Definitionen anpassen würden? – Philippe
Ich glaube, du hast versehentlich nichts und nichts verwirrt. Außerdem, statt Nothing.type, denke ich, dass du keine meinst. – nnythm