包含Coq中N个元素的所有函数的类型

包含Coq中N个元素的所有函数的类型,coq,theorem-proving,Coq,Theorem Proving,我正在学习Coq,作为练习,我想定义一个类型FnArity(N:nat)来编码N参数的所有函数。即: Check FnArity 3 : (forall A B C : Set, A -> B -> C). 应该有效,但是 Check FnArity 2 : (forall A B C D : Set, A -> B -> C -> D). 不应该工作 这是出于教学目的,因此欢迎提供任何相关资源 编辑:从到目前为止的答案来看,我意识到我可能是走错路了,所以我要证

我正在学习Coq,作为练习,我想定义一个类型
FnArity(N:nat)
来编码
N
参数的所有函数。即:

Check FnArity 3 : (forall A B C : Set, A -> B -> C).
应该有效,但是

Check FnArity 2 : (forall A B C D : Set, A -> B -> C -> D).
不应该工作

这是出于教学目的,因此欢迎提供任何相关资源

编辑:从到目前为止的答案来看,我意识到我可能是走错路了,所以我要证明的是一个命题: 组合N个组合运算符相当于组合
f
g
的组合运算符,其中
g
需要N个参数。用哈斯凯尔语来说:

(.).(.) ... N times ... (.).(.) f g = \a1, .. aN -> f (g (a1, .. , aN))
编辑2:用coq术语:

Definition compose { A B C : Type } (F : C -> B) (G : A -> C ) : A -> B :=
  fun x => F ( G (x) ).

Definition compose2 {A1 A2 B C : Type} (F : C -> B) (G : A1 -> A2 -> C)
: A1 -> A2 -> B := fun x y => F ( G x y ).

Definition compose3 {A1 A2 A3 B C : Type} (F : C -> B) (G : A1 -> A2 -> A3 -> C)
: A1 -> A2 -> A3 -> B := fun x y z => F ( G x y z ).

(* The simplest case *)
Theorem dual_compose : forall {A B C D : Type} (f: D -> C) (g : A -> B -> D) ,
                         (compose compose compose) f g = compose2 f g.
Proof. reflexivity. Qed.

Theorem triple_compose : forall {A1 A2 A3 B C : Type} (f: C -> B) (g : A1 -> A2 -> A3 -> C) ,
                         (compose (compose (compose) compose) compose) f g =
                         compose3 f g.

我想要的是定义
composeN

的广义定理。不,这是不可能的,因为
(对于所有的abc:Set,A->B->C)
是无人居住的

Goal (forall A B C : Set, A -> B -> C) -> False.
intros f.
specialize (f True True False).
apply f; trivial.
Qed.

同样地,
检查fNurity 3:(对于所有A B C:集合,A->B->C)。
永远不会工作。

不,这是不可能的,因为
(对于所有A B C:集合,A->B->C)
是无人居住的

Goal (forall A B C : Set, A -> B -> C) -> False.
intros f.
specialize (f True True False).
apply f; trivial.
Qed.

因此,
检查fNurity 3:(对于所有的AB C:Set,A->B->C)。
永远不会工作。

您写下的类型并不完全代表您在问题中所述的类型:
对于所有的AB C,A->B->C
不是三个参数的所有函数的类型,而是两个参数的某些多态函数的类型。您可能打算编写类似于
{A&{B&{C&A->B->C}}}
的内容,其中
A
B
C
是存在量化的。您可能还想说
Compute(FnArity 3)
,而不是使用
Check
命令,因为后者是计算术语的命令(正如jbapple所指出的,任何术语都不能具有您最初编写的类型)

我想这是一段代码,可以满足你的需要。我们首先编写一个函数
FnArityAux1:list Type->Type->Type
,该函数使用列表中给定的参数计算函数类型:

Fixpoint FnArityAux1 (args : list Type) (res : Type) : Type :=
  match args with
  | [] => res
  | T :: args' => T -> FnArityAux1 args' res
  end.
例如,
FnArityAux1[nat;bool]bool
的计算结果为
nat->bool->bool
。然后,我们可以使用此函数定义
FnArity
,如下所示:

Fixpoint FnArityAux2 (args : list Type) (n : nat) : Type :=
  match n with
  | 0 => { T : Type & FnArityAux1 args T }
  | S n' => { T : Type & FnArityAux2 (args ++ [T]) n' }
  end.

Definition FnArity n := FnArityAux2 [] n.

在这个定义中,我们使用另一个辅助函数
FnArityAux2
,它有一个参数
args
,其目的是携带迄今为止产生的所有存在量化类型。对于每个“迭代步骤”,它对另一类型的
T
进行量化,将该类型添加到参数列表中,然后递归。递归结束后,我们使用
FnArityAux1
将所有累积的类型组合成一个函数类型。然后,我们可以定义
FnArity
,只需以一个空列表开始流程——也就是说,根本没有量化的类型

您写下的类型并不完全代表您在问题中所述的类型:
对于所有AB C,A->B->C
不是三个参数的所有函数的类型,而是两个参数的某些多态函数的类型。您可能打算编写类似于
{A&{B&{C&A->B->C}}}
的内容,其中
A
B
C
是存在量化的。您可能还想说
Compute(FnArity 3)
,而不是使用
Check
命令,因为后者是计算术语的命令(正如jbapple所指出的,任何术语都不能具有您最初编写的类型)

我想这是一段代码,可以满足你的需要。我们首先编写一个函数
FnArityAux1:list Type->Type->Type
,该函数使用列表中给定的参数计算函数类型:

Fixpoint FnArityAux1 (args : list Type) (res : Type) : Type :=
  match args with
  | [] => res
  | T :: args' => T -> FnArityAux1 args' res
  end.
例如,
FnArityAux1[nat;bool]bool
的计算结果为
nat->bool->bool
。然后,我们可以使用此函数定义
FnArity
,如下所示:

Fixpoint FnArityAux2 (args : list Type) (n : nat) : Type :=
  match n with
  | 0 => { T : Type & FnArityAux1 args T }
  | S n' => { T : Type & FnArityAux2 (args ++ [T]) n' }
  end.

Definition FnArity n := FnArityAux2 [] n.

在这个定义中,我们使用另一个辅助函数
FnArityAux2
,它有一个参数
args
,其目的是携带迄今为止产生的所有存在量化类型。对于每个“迭代步骤”,它对另一类型的
T
进行量化,将该类型添加到参数列表中,然后递归。递归结束后,我们使用
FnArityAux1
将所有累积的类型组合成一个函数类型。然后,我们可以定义
FnArity
,只需以一个空列表开始流程——也就是说,根本没有量化的类型

您似乎确实回答了我的问题,但我无法使派生类型适用于我的问题。你能检查我的编辑并修改你的答案吗?@fakedrake在这种情况下,你可能只需要输入
FnArityAux1
。我看看能不能想出点什么。还有
&
符号是什么意思。我假设它是某种中缀存在量词,但我找不到关于它的文档?你似乎确实回答了我的问题,但我无法使派生类型解决我的问题。你能检查我的编辑并修改你的答案吗?@fakedrake在这种情况下,你可能只需要输入
FnArityAux1
。我看看能不能想出点什么。还有
&
符号是什么意思。我假设它是某种中缀存在量词,但我找不到关于它的文档?