Rascal中代数数据类型的继承?

时间:2017-07-04 00:40:49

标签: rascal

是的,我在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;

或者,例如,在简化Primitive时与Type匹配。像这样:

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();

我猜有一种方法可以做到这一点,但我还没弄明白......想法?

2 个答案:

答案 0 :(得分: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

人们一直在讨论将隐式链接添加到抽象数据类型中,因为它很有吸引力,可以模拟子类型。我猜这就像Scala的含义一样。陪审团仍在那个问题上。

答案 1 :(得分: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中,并通过构造函数Type包含在prim中。现在reduce(Not(prim(Void())))将缩减为prim(Void())

最终笔记

  • 我们也希望继承(没有像 Solution B 中那样的额外构造函数prim),但由于各种技术原因,我们没有包含它。虽然可取,但我不确定我们会做什么。
  • 请注意default前面的函数,当函数的其他声明不匹配时,它们是 catch all 的情况。
  • 所有功能均为public,除非前面有关键字private