Function Coq中作为函数参数的依赖类型

Function Coq中作为函数参数的依赖类型,function,coq,dependent-type,Function,Coq,Dependent Type,我对Coq很陌生。我正在尝试使用Coq的依赖类型。我想做的是,简单地给一个函数输入一个偶数。例如,在伪代码中: def next_even(n: {n: Integer | n is even}) := { add n 2 } next_even(1) // Coq should show an error next_even(4) // Coq should compute 6 然后我想使用具有不同参数的函数,例如(在伪代码中): 因此,在Coq中,我想做以下工作: Com

我对Coq很陌生。我正在尝试使用Coq的依赖类型。我想做的是,简单地给一个函数输入一个偶数。例如,在伪代码中:

def next_even(n: {n: Integer | n is even}) :=
{
  add n 2
}
next_even(1)    // Coq should show an error
next_even(4)    // Coq should compute 6
然后我想使用具有不同参数的函数,例如(在伪代码中):

因此,在Coq中,我想做以下工作:

Compute (next_even 1).
Compute (next_even 4).

如何构造它?

以下是您在Coq中函数的直接翻译:

From Coq Require Import Arith.

Definition add_two_even (n : {n : nat | Nat.even n = true}) : nat :=
  proj1_sig n + 1.
请注意,您需要使用
proj1_sig
函数从子集类型
{n:nat | nat.偶n=true}
中提取
n
。要使用
add_two_even
,您还需要反过来:从一个数字到
{n | Nat.even=true}
的一个元素。在Coq中,这需要手动证明。对于
n
的具体值,这很容易:

(* The next command fails with a type checking error *)
Fail Compute add_two_even (exist _ 1 eq_refl).
(* The next command succeeds *)
Compute add_two_even (exist _ 4 eq_refl).
exist
构造函数用
px
的证明包装一个值
x
,生成子集类型
{x | px}
的元素。
eq\u refl
术语是
x=x
的任何值的证明。当
n
是一个具体的数字时,Coq可以评估
Nat.偶n
,并找出
eq\u refl
是否是
Nat.偶n=true
的有效证明。当
n
1
时,
Nat.偶n=false
,检查失败,导致第一条错误消息。当
n
4
时,检查成功

n
不是常数,而是任意表达式时,事情会变得更加复杂。证明
Nat.even n=true
可能需要用户指导的详细推理。例如,对于
n
的任何值,我们知道
Nat.偶(n+n)=true
,但Coq不知道。因此,要在形式为
n+n
的东西上调用
add\u two\u偶
,我们需要显示一个引理

Lemma add_n_n_even n : Nat.even (n + n) = true.
Proof.
induction n as [|n IH]; trivial.
now simpl; rewrite <- plus_n_Sm, IH.
Qed.

Definition foo (n : nat) :=
  add_two_even (exist _ (n + n) (add_n_n_even n)).
这个引理对于任意列表的陈述变得更加复杂,因为我们需要一个额外的假设,即两个列表的大小相同。(此处,
x0
是默认值。)

eq\u from\n:
对于所有(T:类型)(x0:T)(s1 s2:列表T),
大小s1=大小s2->
(对于所有i:nat,inth x0 s1 i=nth x0 s2 i)->s1=s2

不使用子集类型是什么意思?那你应该用什么?我认为mathcomp中使用了子集类型,并且有很好的理由,它们比索引归纳类型更易于操作。是的,mathcomp库为子集类型提供了很好的使用模式。我的意思是,对于像
add\u two\u甚至
这样的函数,使用子集类型通常是一个坏主意,在签名上添加的约束可能不会简化此函数的属性。我会尽量在我的回答中更好地解释它。
eq_from_tnth:
  forall (n : nat) (T : Type) (t1 t2 : n.-tuple T),
    (forall i : 'I_n, tnth t1 i = tnth t2 i) -> t1 = t2
eq_from_nth:
  forall (T : Type) (x0 : T) (s1 s2 : list T),
  size s1 = size s2 ->
  (forall i : nat, i < size s1 -> nth x0 s1 i = nth x0 s2 i) -> s1 = s2