2017-07-04 26 views
1

對,我有流氓這個數據類型:Rascal中的代數數據類型的繼承?

data Type = Any() | Void() | Int() | Not(Type l) | And(set[Type] es) | Or(set[Type] es); 

我想要做的就是定義另一種類型是這樣的:

data Primitive = Any() | Void() | Int(); 

然後可以做這樣的事情:

Primitive p = Any(); 
Type d = p; 

或者,例如,在簡化Type時與Primitive匹配。事情是這樣的:

public Type reduce(Not(Primitive p)) = p; 

目前,我能看到的唯一的解決辦法就是擴大上述規則對每一種情況下,像這樣:

public Type reduce(Not(Any)) = Any(); 
public Type reduce(Not(Void)) = Void(); 
public Type reduce(Not(Int)) = Int(); 

我猜是有辦法做到這一點,但我還沒弄清楚......想法?

回答

1

簡短的回答:雖然抽象數據類型可以是擴展(即,它們的定義可以跨模塊延長)沒有直接的繼承

變通

溶液A

data Type = Any() | Void() | Int() | Not(Type l) | And(set[Type] es) | Or(set[Type] es); 

bool isPrim(Any()) = true; 
bool isPrim(Void()) = true; 
bool isPrim(Int()) = true; 
default bool isPrim(Type t) = false; 

Type reduce(Not(Type t)) = t when isPrim(t); 
default Type reduce(Type t) = t; 

這裏Type所有構造都在一個單一的ADT和謂詞isPrim選擇基元。例如,reduce(Not(Void()))將減少到Void()

溶液B

data Primitive = Any() | Void() | Int(); 

data Type = prim(Primitive p) | Not(Type l) | And(set[Type] es) | Or(set[Type] es); 

Type reduce(Not(prim(Primitive p))) = prim(p); 
default Type reduce(Type t) = t; 

這裏的圖元被收集在單獨的ADT Primitive並且它們通過構造prim包括在Type。現在reduce(Not(prim(Void())))將減少到prim(Void())

最後說明

  • 我們也希望有繼承(沒有額外的構造prim溶液B),但我們並沒有包括它的各種技術原因。雖然可取,但我不確定我們會做什麼。
  • 注意函數前面有default,它們是全部收到的情況,當一個函數的其他聲明不匹配時。
  • 所有功能都是public,除非在關鍵詞private之前。
+0

謝謝保羅。實際上,'isPrim'匹配程序看起來比使用單獨的'prim'構造函數更好。我會給它一個旋風。 – redjamjar

1

不錯的問題。 Rascal不具有用戶定義的子類型輸入功能,而對數據類型的輸入則是名義上的。這在理論上回答你的問題,那麼在實踐中這是如何工作的?

  • 對於語法類型,數據類型的答案略有不同,所以這裏跟隨兩個故事;
  • 有很多不同的習語來模擬數據結構的層次結構,爲了簡單起見,我們在這裏只顯示三個;

下面就來擴展數據類型的新功能不涉及增加新類型的方式,這將產生的你打算什麼過近似模型:

// first the primitive types are defined (I've added Not here to make a point later): 
data Type = Any() | Void() | Int() | Not(Type l); 

// then the extension is added (perhaps in a different module) 
data Type = And(set[Type] es) | Or(set[Type] es); 

// the second definition adds its alternatives also to the child of `Not`. 

第二種方式是更接近實際的分機,因爲原來Type不延長,也沒有「垃圾」意外地補充道:

// we give the original type a unique name: 
data Primitive = Any() | Void() | Int(); 

// For the extension the Primitive type is not polluted with the new constructors, but 
// it was wrapped inside a singleton constructor `prim` 
data Type = prim(Primitive super) | And(set[Type] es) | Or(set[Type] es); 

當然,這第二個解決方案將讓你添加prim可能模式匹配的構造函數可能會匹配,但/深度匹配運算符將允許您在可能的情況下忽略它。例如:

bool evalt(prim(p)) = evalp(p); 
bool evalp(Any()) = true; 
bool evalp(Not(p)) = !evalp(p); 

bool containsVoid(Type t) = /Void() := t; 

現在對於語法類型的故事是類似的,但因爲在語法類型鏈規則的是無形的,它提供了一些額外的味道:

syntax Primitive = "any" | "void" | "int"; 

// notice the first chain rule or "injection" of Primitive into Type: 
syntax Type = Primitive | left Type "∧" Type > left Type "∨" Type; 

bool evalt((Type) `any`) = true; // the chain rule is parsed but invisible 

人們一直在討論隱式鏈接添加到抽象數據類型也是如此,因爲它很有吸引力來模擬子類型。我想這就像斯卡拉的暗示。陪審團仍然在那個之外。

+0

謝謝尤爾根。我認爲'prim'構造函數可能會訣竅。這是一個有點難看,因爲你說,但得到它的工作是我現在的主要關注:) – redjamjar