包含Coq中N个元素的所有函数的类型
我正在学习Coq,作为练习,我想定义一个类型包含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). 不应该工作 这是出于教学目的,因此欢迎提供任何相关资源 编辑:从到目前为止的答案来看,我意识到我可能是走错路了,所以我要证
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
。我看看能不能想出点什么。还有&
符号是什么意思。我假设它是某种中缀存在量词,但我找不到关于它的文档?