Oto problem z projektowaniem, z którym miałem do czynienia wielokrotnie. Załóżmy, że budujesz kompilator, w jaki sposób przechowujesz typy w drzewach?Projektowanie niezmiennych, dających się sortować, drzew
Rozważmy prosty Expr
i Type
hierarchię, i zakładamy, że Plus
i Equals
są polimorficzne (plus na logicznych w zaledwie ||
, na przykład).
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
// ...
Załóżmy dalej, że nie wiem, rodzaj identyfikatorów kiedy skonstruowania wyrażenia drzew, a zatem nie może znać typ poprzez budowę. Teraz typowa funkcja typechecking mógłby wyglądać następująco:
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.
}
Jest to dość proste do napisania, ale pochodzi z dwóch głównych problemów:
Expr
s są zmienne. Nikt nie lubi mutacji.- Nie można rozróżniać wyrażeń typu i bez typów. Nie mogę napisać funkcji, której podpis wskazuje, że jej argument musi być wyrażeniem pisanym na maszynie.
Moje pytanie jest następujące. Co to jest dobrym sposobem (nie śmiem powiedzieć wzorca projektowego), aby określić możliwie bez typu drzew takie, że:
- muszę zdefiniować hierarchię
Expr
tylko raz. - Wpisane i bez typu drzewa mają różne typy i mogę je zmienić na niezgodne.
Edit: Kolejny wymóg jest, że powinien pracować dla systemów typu z nieograniczonego i nieprzewidywalnej liczby typów (myśleć: case class ClassType(classID : String) extends Type
, na przykład).
Przykład użycia będzie świetny. Jak przepiszesz "typeCheck" w swoim systemie? –
Wygląda na to, że mógł być tym, czego szukałem. Jak sugeruje Eugene, czy mógłbyś pokazać, w jaki sposób dostosowałbyś moją funkcję 'typeCheck' do swoich definicji? – Philippe
Myślę, że przypadkowo pomyliłeś Brak i Nic. Ponadto, zamiast Nic.type, myślę, że masz na myśli Brak. – nnythm