子集参数

时间:2011-03-04 13:09:17

标签: coq

我有一个参数设置:

Parameter Q:Set.

现在我想定义另一个作为Q子集的参数。例如:

Parameter F: subset Q.

我如何定义?我想我可以稍后将限制添加为公理,但直接用F的类型表达它似乎更自然。

1 个答案:

答案 0 :(得分:8)

你无法直接表达。

Set中的对象视为数学集是错误的。 Set是一种数据类型,与编程语言中的类型相同(除了Coq的类型非常强大)。

Coq没有子类型¹。如果两种类型FQ不同,那么就数学模型而言,它们是不相交的。

通常的方法是将F声明为完全相关的集合,并声明从FQ的规范注入。除了显而易见之外,您还需要指定该注入的任何有趣属性。

Parameter Q : Set.
Parameter F : Set.
Parameter inj_F_Q : F -> Q.
Axiom inj_F_Q_inj : forall x y : F, inj_F_Q x = inj_F_Q y -> x = y.
Coercion inj_F_Q : F >-> Q.

最后一行宣布了从FQ的强制行为。这允许您在上下文需要类型F的任何位置放置Q类型的对象。类型推理引擎将插入对inj_F_Q的调用。你需要偶尔明确写出强制,因为类型推理引擎虽然非常好,但并不完美(完美在数学上是不可能的)。 Coq参考手册中有一章有关强制的内容;你应该至少浏览它。

另一种方法是使用扩展属性定义子集,即在集合(类型)P上声明谓词Q并从F定义P

Parameter Q : Set.
Parameter P : Q -> Prop.
Definition G := sig P.
Definition inj_G_Q : G -> Q := @proj1_sig Q P.
Coercion inj_G_Q : G >-> Q.

sig是规范,即弱和类型,即由对象和所述对象具有某种属性的证据组成的对。 sig P等效于{x | P x}(即语法糖sig (fun x => P x))。你必须决定你喜欢短形式还是长形式(你需要保持一致)。使用弱金额时,Program白话通常很有用。

¹ 模块语言中有子类型,但这与此无关。并且强制假冒了很多用途的子类型,但它们并不是真实的东西。