Types coq集合或类型如何成为命题
我正在读一本关于Coq的教程。它构造了一个Types coq集合或类型如何成为命题,types,set,coq,boolean-expression,first-order-logic,Types,Set,Coq,Boolean Expression,First Order Logic,我正在读一本关于Coq的教程。它构造了一个bool类型,如下所示: Coq < Inductive bool : Set := true | false. bool is defined bool_rect is defined bool_ind is defined bool_rec is defined CoqP false->forall b:bool,P b CoqSet,P true->P false->对于所有b:bool,P b CoqType,P true->P fal
bool
类型,如下所示:
Coq < Inductive bool : Set := true | false.
bool is defined
bool_rect is defined
bool_ind is defined
bool_rec is defined
Coq
然后,它显示了这些东西中的每一个都在使用“检查”
CoqProp,P true->P false->forall b:bool,P b
Coq<检查bool\u rec。
布卢雷克
:对于所有P:bool->Set,P true->P false->对于所有b:bool,P b
Coq<检查边界。
布尔
:forall P:bool->Type,P true->P false->forall b:bool,P b
我明白你的意思。它说,如果某个事物适用于true
和false
,那么它适用于bool
中的所有b
(因为只有这两个)
但是我不明白
bool_rec
或bool_rect
的表达式是什么意思。似乎P true
(这是bool_rec
的集合
和bool_rect
的类型
)被视为命题值。我在这里遗漏了什么?你对bool_ind
的直觉是正确的,但是思考一下为什么bool_ind
意味着你所说的可能有助于澄清另外两个。我们知道
bool_ind : forall P : bool -> Prop,
P true ->
P false ->
forall b : bool,
P b
如果我们把它作为一个逻辑公式来理解,我们会得到与你相同的解读:
- 对于
eans上的每个谓词bool
,P
- 如果
成立,并且P true
- 如果
保持不变,则P false
- 对于每个布尔值
,b
有效pb
- 如果
- 给定一个值
,P:bool->Prop
- A值
Pt:P true
- A值
,以及Pf:P false
- A值
,b:bool
- 我们可以构造一个值
Pb:Pb
- 我们可以构造一个值
- A值
->
对应于蕴涵,依赖函数类型对应于所有
对应于通用量化。(这个符号很有启发性:-)所以在Coq中,为了证明φ→ ψ、 我们必须构造一个φ->ψ
类型的值:一个取φ
类型的值(或者换句话说,命题φ的证明)并用它构造ψ
类型的值(命题ψ的证明)
在Coq中,我们可以用这种方式来考虑所有类型,不管这些类型是生活在集合
,类型
,还是属性
。(所以,当你说“好像P真(它是BoO-ReC的集合和BooLeReCT的类型))被当作一个命题值,“你是对的!”,例如,让我们考虑我们如何实现代码> BooLoId我们自己。我们将首先列出函数的所有参数及其返回类型:
Definition bool_ind' (P : bool -> Prop)
(Pt : P true)
(Pf : P false)
(b : bool)
: P b :=
到目前为止,一切顺利。此时,我们希望返回类型为pb
的内容,但我们不知道b
是什么。因此,在这些情况下,我们通常会进行模式匹配:
match b with
Definition bool_to_nat_match (b : bool) : nat :=
match b with
| true => 1
| false => 0
end.
现在有两个案例。首先,b
可以是true
。在这种情况下,我们必须返回类型为P true
,幸运的是我们有这样一个值:Pt
| true => Pt
false
的情况类似:
| false => Pf
end.
注意,当我们实现bool\u ind'
时,它看起来不是很“可靠”,而是很“程序化”。当然,多亏了Curry Howard的信件,这些都是一样的。但请注意,对于其他两个功能,同样的实现就足够了:
Definition bool_rec' (P : bool -> Set)
(Pt : P true)
(Pf : P false)
(b : bool)
: P b :=
match b with
| true => Pt
| false => Pf
end.
Definition bool_rect' (P : bool -> Type)
(Pt : P true)
(Pf : P false)
(b : bool)
: P b :=
match b with
| true => Pt
| false => Pf
end.
看看这个计算定义,我们可以从另一个角度了解bool_ind
、bool_rec
、和bool rect
:它们封装了谈论bool
的每一个值所需的知识。但不管怎样,我们都在打包这些信息:如果我知道一些关于true
的信息,以及一些关于false
的信息,那么我就知道所有的bool
了
bool_{ind,rec,rect}
函数的定义抽象了我们在布尔函数上编写函数的通常方式:一个参数对应于真分支,一个参数对应于假分支。或者,换句话说:这些函数只是if
语句。在非依赖类型的语言中,对于所有S:Set,S->S->bool->S,它们可以使用更简单的类型:
Definition bool_simple_rec (S : Set) (St : P) (Sf : P) (b : bool) : S :=
match b with
| true => St
| false => Sf
end.
然而,因为类型可以依赖于值,所以我们必须在所有的类型中穿行b
。但是,如果我们不希望这样,我们可以使用更通用的函数并告诉:
Definition bool_simple_rec' (S : Set) : S -> S -> bool -> S :=
bool_rec (fun _ => S).
没有人说过我们的p:bool->Set
必须使用bool
对于递归类型,所有这些函数都非常有趣。例如,Coq具有以下类型的自然数:
Inductive nat : Set := O : nat | S : nat -> nat.
我们有
nat_ind : forall P : nat -> Prop,
P O ->
(forall n' : nat, P n' -> P (S n')) ->
forall n : nat,
P n
以及相应的nat\u rec
和nat\u rect
。(读者练习:直接实现这些功能。)
乍一看,这只是数学归纳法的原理。然而,这也是我们在nat
s上编写递归函数的方式;它们是一样的。一般来说,nat
上的递归函数看起来像
fix f n => match n with
| O => ...
| S n' => ... f n' ...
end
Definition bool_to_nat_match (b : bool) : nat :=
match b with
| true => 1
| false => 0
end.
Definition bool_to_nat_rec : bool -> nat :=
bool_rec (fun _ => nat) 1 0.
Goal bool_to_nat_match = bool_to_nat_rec.
Proof. reflexivity. Qed.
Inductive has_if (A : Type) : bool -> Type :=
| has : A -> has_if A true
| lacks : has_if A false.
Definition keep_if_match' (A : Type) (a : A) (b : bool) : has_if A b :=
match b with
| true => has A a
| false => lacks A
end.
Definition keep_if_rect (A : Type) (a : A) : forall b : bool, has_if A b :=
bool_rect (has_if A) (has A a) (lacks A).
Goal keep_if_match = keep_if_rect.
Proof. reflexivity. Qed.
Inductive vec (A : Type) : nat -> Type :=
| vnil : vec A O
| vcons : forall n, A -> vec A n -> vec A (S n).
Arguments vnil {A}.
Arguments vcons {A n} _ _.
Fixpoint vreplicate_fix {A : Type} (n : nat) (a : A) : vec A n :=
match n with
| O => vnil
| S n' => vcons a (vreplicate_fix n' a)
end.
Definition vreplicate_rect {A : Type} (n : nat) (a : A) : vec A n :=
nat_rect (vec A) vnil (fun n' v => vcons a v) n.
fun n' v => vcons a v
fun (n' : nat) (v : vec A n') => vcons a v : vec A (S n')
Eval simpl in vreplicate_fix 0 tt.
Eval simpl in vreplicate_rect 0 tt.
(* both => = vnil : vec unit 0 *)
Eval simpl in vreplicate_fix 3 true.
Eval simpl in vreplicate_rect 3 true.
(* both => = vcons true (vcons true (vcons true vnil)) : vec bool 3 *)
(* Note: these two functions do the same thing, but are not syntactically
equal; the former is a fixpoint, the latter is a function which returns a
fixpoint. This sort of equality is all you generally need in practice. *)
Goal forall (A : Type) (a : A) (n : nat),
vreplicate_fix n a = vreplicate_rect n a.
Proof. induction n; [|simpl; rewrite IHn]; reflexivity. Qed.
Fixpoint nat_rect' (P : nat -> Type)
(base_case : P 0)
(recurse : forall n', P n' -> P (S n'))
(n : nat)
: P n :=
match n with
| O => base_case
| S n' => recurse n' (nat_rect' P base_case recurse n')
end.