处理 `{ x : nat | 形式的(子)类型的最佳方式x >= 13 /\ x <= 19 }`?
Best way to handle (sub) types of the form `{ x : nat | x >= 13 /\ x <= 19 }`?
Coq 让我定义这个:
Definition teenagers : Set := { x : nat | x >= 13 /\ x <= 19 }.
还有:
Variable Julia:teenagers.
但不是 :
Example minus_20 : forall x:teenagers, x<20.
或:
Example Julia_fact1 : Julia > 12.
这是因为 Julia(类型 teenagers)无法与 12(nat)进行比较。
Q: 我应该如何通知 Coq Julia 的支持类型是 nat 以便我可以写任何关于她的有用信息?
Q': 我对青少年的定义似乎是一个死胡同;它比建设性更具陈述性,我似乎已经失去了 nat 的归纳特性。我怎样才能显示它的居民?如果没有办法,我还是可以坚持使用nat,使用Prop和函数。 (这里是菜鸟,自学不到一周Pierce's SF)。
您在 teenagers
中使用的模式是 "subType" 模式的一个实例。正如您所注意到的,{ x : nat | P x }
不同于 nat
。目前,Coq 几乎没有提供有效处理这些类型的支持,但如果您限制为 "well-behaved" class 的 P
,您实际上可以以合理的方式工作。 [这真的应该成为 Coq FAQ 顺便说一句]
从长远来看,您可能希望对此模式使用特殊支持。 math-comp 库 subType
接口提供了这种支持的一个很好的例子。
描述这个界面超出了你原来的问题,所以我将以一些评论结束:
在您的 minus_20
示例中,您想要使用青少年数据类型的 第一个投影 。尝试 forall x : teenagers, proj1_sig x < 20
。如果您将投影声明为 Coercion
:
,Coq 可以尝试自动插入此类投影
Require Import Omega.
Definition teenagers : Set :=
{ x : nat | x >= 13 /\ x <= 19 }.
Coercion teen_to_nat := fun x : teenagers => proj1_sig x.
Implicit Type t : teenagers.
Lemma u t : t < 20.
Proof. now destruct t; simpl; omega. Qed.
正如您正确观察到的,{ x : T | P x }
在 Coq 中与 x
不同。原则上,您不能将推理从 T
类型的对象转移到类型 { x : T | P x }
的对象,因为您还必须另外推理类型 P x
的对象。但是对于P
的宽class,可以证明teen_to_nat
投影是单射的,即:
forall t1 t2, teen_to_nat t1 = teen_to_nat t2 -> t1 = t2.
然后,可以将对基类型的推理转移到子类型。另见:
[edit]: 我在 math-comp 中添加了几个典型的子类型示例,因为我认为它们很好地说明了这个概念:
- 大小列表或
n.-tuples
。长度为 n 的列表在 math-comp 中表示为一对单个列表加上大小证明,也就是说 n.-tuple T = { s : seq T | size s == n}
。由于单射性和强制性,您可以在元组上使用所有常规列表函数,它们工作正常。
- 有界自然数或序数:类似地,类型
'I_n = { x : nat | x < n }
与自然数几乎相同,但有界。
Coq 让我定义这个:
Definition teenagers : Set := { x : nat | x >= 13 /\ x <= 19 }.
还有:
Variable Julia:teenagers.
但不是 :
Example minus_20 : forall x:teenagers, x<20.
或:
Example Julia_fact1 : Julia > 12.
这是因为 Julia(类型 teenagers)无法与 12(nat)进行比较。
Q: 我应该如何通知 Coq Julia 的支持类型是 nat 以便我可以写任何关于她的有用信息?
Q': 我对青少年的定义似乎是一个死胡同;它比建设性更具陈述性,我似乎已经失去了 nat 的归纳特性。我怎样才能显示它的居民?如果没有办法,我还是可以坚持使用nat,使用Prop和函数。 (这里是菜鸟,自学不到一周Pierce's SF)。
您在 teenagers
中使用的模式是 "subType" 模式的一个实例。正如您所注意到的,{ x : nat | P x }
不同于 nat
。目前,Coq 几乎没有提供有效处理这些类型的支持,但如果您限制为 "well-behaved" class 的 P
,您实际上可以以合理的方式工作。 [这真的应该成为 Coq FAQ 顺便说一句]
从长远来看,您可能希望对此模式使用特殊支持。 math-comp 库 subType
接口提供了这种支持的一个很好的例子。
描述这个界面超出了你原来的问题,所以我将以一些评论结束:
在您的
,Coq 可以尝试自动插入此类投影minus_20
示例中,您想要使用青少年数据类型的 第一个投影 。尝试forall x : teenagers, proj1_sig x < 20
。如果您将投影声明为Coercion
:Require Import Omega. Definition teenagers : Set := { x : nat | x >= 13 /\ x <= 19 }. Coercion teen_to_nat := fun x : teenagers => proj1_sig x. Implicit Type t : teenagers. Lemma u t : t < 20. Proof. now destruct t; simpl; omega. Qed.
正如您正确观察到的,
{ x : T | P x }
在 Coq 中与x
不同。原则上,您不能将推理从T
类型的对象转移到类型{ x : T | P x }
的对象,因为您还必须另外推理类型P x
的对象。但是对于P
的宽class,可以证明teen_to_nat
投影是单射的,即:forall t1 t2, teen_to_nat t1 = teen_to_nat t2 -> t1 = t2.
然后,可以将对基类型的推理转移到子类型。另见:
[edit]: 我在 math-comp 中添加了几个典型的子类型示例,因为我认为它们很好地说明了这个概念:
- 大小列表或
n.-tuples
。长度为 n 的列表在 math-comp 中表示为一对单个列表加上大小证明,也就是说n.-tuple T = { s : seq T | size s == n}
。由于单射性和强制性,您可以在元组上使用所有常规列表函数,它们工作正常。 - 有界自然数或序数:类似地,类型
'I_n = { x : nat | x < n }
与自然数几乎相同,但有界。