Coq 使子集类型与函数应用程序兼容

Coq 使子集类型与函数应用程序兼容,coq,Coq,我试图熟悉Coq中的子集类型,我遇到了一种我不知道如何继续的用例。考虑一个期望大于2的自然数的函数,以及期望大于2和小于10的自然数的另一个函数。在后一个函数中,我想调用前一个函数,这应该是可能的,但似乎我必须做一些事情,使其类型适合于函数应用程序。这就是我想做的: Definition add_one_if_gt_2 (i : {i1 : nat | i1 > 2}) := (proj1_sig i) + 1. Definition add_one_if_gt_2_and_lt_10 (

我试图熟悉Coq中的子集类型,我遇到了一种我不知道如何继续的用例。考虑一个期望大于2的自然数的函数,以及期望大于2和小于10的自然数的另一个函数。在后一个函数中,我想调用前一个函数,这应该是可能的,但似乎我必须做一些事情,使其类型适合于函数应用程序。这就是我想做的:

Definition add_one_if_gt_2 (i : {i1 : nat | i1 > 2}) := (proj1_sig i) + 1.
Definition add_one_if_gt_2_and_lt_10 (i : {i1 : nat | i1 > 2 /\ i1 < 10}) := add_one_if_gt_2 i.
definitionadd_one_如果_gt_2(i:{i1:nat | i1>2}):=(proj1_sig i)+1。
定义add_one_if_gt_2_和_lt_10(i:{i1:nat|i1>2/\i1<10}):=add_one_if_gt_2 i。
中缺少什么?如果添加一个和一个以进行打字检查?一般来说,对于可能兼容的更复杂的子集类型,通常的处理方法是什么


另外,为了以防万一,我在子集类型规范中使用了
i1
,但是如果我使用
I
,它似乎也可以工作,尽管我不知道是否存在任何潜在问题,因为参数名称也是
I
。对这两个变量使用
i
会有问题吗?

一种可能是使用
程序
功能:

Require Import Program.

Program Definition add_one_if_gt_2 (i : {i1 : nat | i1 > 2}) :=
  i + 1.
Program Definition add_one_if_gt_2_and_lt_10
  (i : {i1 : nat | i1 > 2 /\ i1 < 10}) :=
add_one_if_gt_2 i.
需要导入程序。
程序定义添加_one_如果_gt_2(i:{i1:nat | i1>2}):=
i+1。
程序定义添加一个如果2和10
(i:{i1:nat|i1>2/\i1<10}):=
如果第二个i,则添加第1个i。
如果您仔细阅读这段代码,您会注意到系统正在生成关于“义务”的消息——但在本例中,所有义务都非常简单,系统可以自动自行解析它们,并且定义立即完成。(在这种情况下,第二个定义产生的义务是
i>2/\i<10
意味着
i>2


在其他无法轻松解决义务的情况下,您可能会得到挂起的义务。在这种情况下,您可以使用Gallina指令,例如
下一个义务。
来进入证明模式并自己证明它们。(有关更多信息,请参阅Coq文档的相应章节。)

您手动执行此操作,因为不难解构
{i1:nat | i1>2/\i1<10}
类型的术语,它基本上是
nat
i1
)的三元组,还有两个证明:
i1>2
i2<10
。我们要做的是分解这个三元组,扔掉第三个组件,并将其重新打包成一个
{i1:nat | i1>2}
类型的项,这是一对:

Definition add_one_if_gt_2 (i : {i1 : nat | i1 > 2}) :=
  S (proj1_sig i).

Definition add_one_if_gt_2_and_lt_10 (i : {i1 : nat | i1 > 2 /\ i1 < 10}) :=
  let '(exist _ i1 (conj i1_gt2 _)) := i in
  add_one_if_gt_2 (exist _ i1 i1_gt2).
使用强制机制,您可以将上述定义简化为:

Coercion sig_of_sig2 : sig2 >-> sig.

Definition add_one_if_gt_2_and_lt_10_sig2' (i : {i1 : nat | i1 > 2 & i1 < 10}) :=
  add_one_if_gt_2 i.
强制sig\u的sig2:sig2>->sig。
定义加上_one_if_gt_2_和_lt_10_sig2'(i:{i1:nat | i1>2&i1<10}):=
如果第二个i,则添加第1个i。
这正是您试图应用的解决方案


如果您不熟悉强制:如果遇到可以修复的类型错误,此机制会自动插入sig\u of_sig2(或其他合适的强制)。

对于子集类型,您会发现,有时很难对它们的相等性进行推理,因为平等的证明开始出现,这是违反直觉的。如果这会咬到你,我建议你看看在医院里是如何治疗的。
Definition add_one_if_gt_2_and_lt_10_sig2 (i : {i1 : nat | i1 > 2 & i1 < 10}) :=
  add_one_if_gt_2 (sig_of_sig2 i).
Coercion sig_of_sig2 : sig2 >-> sig.

Definition add_one_if_gt_2_and_lt_10_sig2' (i : {i1 : nat | i1 > 2 & i1 < 10}) :=
  add_one_if_gt_2 i.