Types 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

我正在读一本关于Coq的教程。它构造了一个
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
如果我们把它作为一个逻辑公式来理解,我们会得到与你相同的解读:

  • 对于
    bool
    eans上的每个谓词
    P
    • 如果
      P true
      成立,并且
    • 如果
      P false
      保持不变,则
    • 对于每个布尔值
      b
      • pb
        有效
但这不仅仅是一个逻辑公式,它是一种类型。具体来说,它是一种(依赖的)函数类型。作为一种函数类型,它说(如果您允许我为未命名的参数和结果随意命名):

  • 给定一个值
    P:bool->Prop
    • A值
      Pt:P true
    • A值
      Pf:P false
      ,以及
    • A值
      b:bool
      • 我们可以构造一个值
        Pb:Pb
(当然,这是一个curried函数,因此有其他方法将类型分解为散文,但这对于我们的目的来说是最清楚的。)

这里最重要的一点是,Coq作为一种编程语言(反之亦然)起到了定理证明的作用:类型是命题,值是这些命题的证明。例如,简单函数类型
->
对应于蕴涵,依赖函数类型
对应于所有
对应于通用量化。(这个符号很有启发性:-)所以在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.