是的,我在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();
我猜有一种方法可以做到这一点,但我还没弄明白......想法?
答案 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())
。
最终笔记
prim
),但由于各种技术原因,我们没有包含它。虽然可取,但我不确定我们会做什么。default
前面的函数,当函数的其他声明不匹配时,它们是 catch all 的情况。public
,除非前面有关键字private
。