這是我反覆面對的設計問題。假設你正在構建一個編譯器,你如何將這些類型存儲在樹中?不可改變的,可鍵入的樹木的設計
考慮一個簡單的Expr
和Type
層次,並假設Plus
和Equals
是多態(加上在短短||
布爾值,例如)。
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
// ...
進一步假設我在構建表達式樹時不知道標識符的類型,因此不能通過構造知道類型。 現在一個典型的類型檢查功能看起來是這樣的:
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.
}
這是相當直白地寫,但帶有兩個主要問題:
Expr
s爲可變的。沒有人喜歡突變。- 無法區分有類型和無類型的表達式。我不能寫一個函數,它的簽名指定它的參數必須是一個類型化的表達式。
所以我的問題是以下。什麼是一個好方法(我不敢說設計模式)來定義可能無類型的樹這樣的:
- 我需要定義只有一次
Expr
層次。 - 有類型和無類型的樹有不同的類型,我可以選擇使它們不兼容。
編輯:還有一個要求是它應類型的系統工作,無界和不可預知號碼類型(認爲:case class ClassType(classID : String) extends Type
,例如)。
用法示例很棒。你將如何在你的系統中重寫'typeCheck'? –
這看起來可能是我正在尋找的東西。正如Eugene所建議的那樣,你能否展示一下如何使我的'typeCheck'函數適應你的定義? – Philippe
我想你已經不小心混淆了None和Nothing。此外,而不是Nothing.type,我認爲你的意思是無。 – nnythm