归纳命题在 Coq 中如何运作?

2023-12-21

我正在阅读软件基础中的 IndProp 和 Adam Chlipala 的第 4 章书,但我在理解归纳命题时遇到了困难。

为了运行示例,让我们使用:

Inductive ev : nat -> Prop :=
| ev_0 : ev 0
| ev_SS : forall n : nat, ev n -> ev (S (S n)).

我想我确实理解“正常”类型使用Set like:

Inductive nat : Set :=
  | O : nat
  | S : nat -> nat.

和类似的事情O只返回类型的单个对象nat and S O正在获取类型的对象nat并返回另一个不同的同一类型之一nat。我想我所说的不同对象是指它们具有不同的值。

我感到困惑的是归纳道具的构造函数与归纳类型到底有何不同Set. For Set看起来它们只是充当函数,一个接受值并返回更多该类型值的函数。但对于归纳命题,我很难弄清楚它们的作用。

例如采取ev_0举一个简单的例子。我假设这是命题对象(值)的名称ev 0。既然是它自己ev 0必须是一个Prop一个提议。但究竟是什么让它成为事实呢?如果这是一个提议,我认为它可能是错误的。我想归纳法让我感到困惑。ev是“返回某种类型的对象的函数(命题)”,所以 ev 0 只是一个命题,但我们还没有说什么ev 0应该意味着(与我对自然数的定义不同,基本情况很清楚它在做什么)。在 python 中我希望看到

n == 0: return True

或基本情况的东西。但在这种情况下,它似乎循环指向自身而不是类似的东西True。我知道我有一个根本性的误解,但我不知道我到底不理解什么。

另外让我困惑的是命名。在里面nat名字O对于建造/构造物体至关重要。但在归纳定义中ev_0似乎更像是一个标签/指向真实值的指针ev 0。所以我假设ev_SS == ev_0 -? ev 2确实没有意义,但我不知道为什么。这里的标签与使用感应类型的标签有何不同?set?

For ev_SS这更令人困惑。因为我不知道标签在做什么,这当然让我感到困惑,但看看它是如何指向的:

forall n : nat, ev n -> ev (S (S n))

所以给定一个自然数n我认为它返回了命题ev n -> ev (S (S n))(我假设forall n : nat不是命题对象的一部分,它只是用来指示返回命题的构造函数何时起作用)。所以forall n : nat, ev n -> ev (S (S n))这并不是一个真正的提议,但是ev n -> ev (S (S n)).

有人可以帮我澄清归纳命题类型在 Coq 中是如何真正工作的吗?


注意我并不真正理解之间的区别Set vs Type但我相信这本身就是另一篇文章了。


更多评论:

我又玩了一下这个,然后做了:

Check ev_SS

令我惊讶的是:

ev_SS
     : forall n : nat, ev n -> ev (S (S n))

我认为这是出乎意料的,因为我没想到这种类型ev_SS(除非我误解了什么Check应该做的)将是函数本身的定义。我以为ev_SS是一个构造函数,所以在我看来,我认为在这种情况下会进行映射nat -> Prop所以这当然是我所期望的类型。


所以,首先,你对此感到困惑是正常的,但它可能比你想象的要简单!

您对两个不同的概念感到困惑,所以让我们逐一讨论它们。首先,你提到ev 0是一个命题,并想知道是什么让它成为现实。在某些时候你会了解到命题和类型是相同的东西,并且它们之间的区别Prop and Set and Type并不是说这些东西本质上是不同的。

因此,当您定义类型(或命题)时nat,您正在创建一个新类型,并描述其中存在哪些值。你声明有一个值O, 这是一个nat。并且你声明有一个参数化值S, 这是一个nat,当通过一个nat.

同样,当你定义类型(或命题)时ev,您正在创建一个新类型(嗯,它实际上是一个由类型值索引的类型系列nat),并描述其中存在哪些值ev类型。你声明有一个值ev_0,这是一个ev 0。并且你声明有一个参数化值ev_SS,这是一个ev (S (S n)),当通过一个n : nat and an ev n.

So you通过在其中创造价值的方式使该主张成为现实。您还可以通过没有构造函数或具有永远无法调用的构造函数来定义伪命题:

Inductive MyFalse1 := . (* no constructor! *)

Inductive MyFalse2 :=
| TryToConstructMe : False ->  MyFalse2
| ThisWontWorkEither : 0 = 1 -> MyFalse2
.

我已经声明了两个 now 类型(或命题),但无法见证它们,因为它们要么没有构造函数,要么无法调用这些构造函数。


现在关于事物的命名,ev_0, ev_SS, O, and S都是同一种实体:构造函数。我不知道你为什么这么想ev_0是一个指向值的指针ev 0.

没有赋予任何意义ev n作为一个命题,除非有一种方法可以构造具有类型的值,否则它可能是正确的命题ev n,如果无法构造具有类型的值,则可能为 falseev n.

但请注意ev n经过精心设计,正是为了满足这些需求ns 是均匀的,并且正是那些无人居住的n这很奇怪。正是在这个意义上ev抓住一个命题。如果您收到类型的值ev n,它本质上断言n是偶数,因为类型ev n只包含偶数值的居民:

  • ev 0包含 1 名居民 (ev_0)
  • ev 1包含 0 名居民
  • ev 2包含 1 名居民 (ev_SS 0 ev_0)
  • ev 3包含 0 名居民
  • ev 4包含 1 名居民 (ev_SS 2 (ev_SS 0 ev_0))
  • etc.

最后,对于之间的区别Set, Prop, and Type,这些都是您可以在其中创建归纳类型的宇宙,但它们有一定的限制。

Prop实现代码生成的优化。从本质上讲,它是程序员将某种类型标记为仅用于验证目的而不用于计算目的的一种方法。因此,类型检查器将迫使您永远不要在以下范围内计算证明:Prop宇宙,代码生成将知道它可以丢弃这些证明,因为它们不参与计算行为。

Set只是一个限制Prop以避免处理宇宙层面。直到稍后的学习过程中,您才真正需要理解这一点。

你真的应该试着不去想Prop作为一种神奇的东西不同于Set.


以下内容可能对您有帮助:我们可以重写以下定义nat and ev,以完全等价的方式,如:

Inductive nat1 : Set :=
| O : nat1
| S : nat1 -> nat1
.
(* is the same as *)
Inductive nat1 : Set :=
| O : nat1
| S : forall (n : nat1), nat1
.

(* and *)
Inductive ev : nat -> Prop :=
| ev_0 : ev 0
| ev_SS : forall (n : nat), ev n -> ev (S (S n))
.
(* is the same as *)
Inductive ev : nat -> Prop :=
| ev_0 : ev 0
| ev_SS : forall (n : nat) (e : ev n), ev (S (S n))
.

任何时候你看到类似的类型a -> b,这实际上是一个简写forall (_ : a), b,也就是说,我们期望输入类型a,并返回类型的输出b.

我们写作的原因forall (n : nat) in ev_SS是我们have为第一个参数命名,因为第二个参数的类型将取决于它(第二个参数的类型为ev n).

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

归纳命题在 Coq 中如何运作? 的相关文章

  • 如何在 Coq 中使用归纳类型来处理案例

    我想使用destruct通过案例来证明陈述的策略 我在网上读了几个例子 但我很困惑 有人可以更好地解释一下吗 这是一个小例子 还有其他方法可以解决它 但尝试使用destruct Inductive three zero one two Le
  • Coq 中是否有一套最小完整的策略?

    我见过很多 Coq 策略 它们在功能上是相互重叠的 例如 当你在假设中得到确切的结论时 你可以使用assumption apply exact trivial 也许还有其他人 其他例子包括destruct and induction对于无感
  • 在 Coq 中使用我自己的 == 运算符重写策略

    我试图直接从字段的公理证明简单的字段属性 经过对 Coq 原生现场支持的一些实验 像这个 我决定最好简单地写下 10 条公理并使其自成一体 我在需要使用的时候遇到了困难rewrite与我自己的 运算符自然不起作用 我意识到我必须添加一些我的
  • 如何指示两种 Coq 电感类型尺寸的减小

    我正在尝试定义game组合游戏的归纳型 我想要一个比较方法来判断两个游戏是否相同lessOrEq greatOrEq lessOrConf or greatOrConf 然后我可以检查两个游戏是否相等 如果它们都是 lessOrEq and
  • 如何在 Coq 中将一条线的公理定义为两个点

    我想找一个例子axiom in Coq类似于几何中的线公理 如果给定两个点 则这两点之间存在一条线 我想看看如何在 Coq 中定义它 本质上选择这个简单的直线公理来看看如何定义一些非常原始的东西 因为我很难在自然语言之外定义它 具体来说 我
  • 证明唯一的零长度向量为零

    我有一个类型定义为 Inductive bits nat gt Set bitsNil bits 0 bitsCons forall l bool gt bits l gt bits S l 我试图证明 Lemma emptyIsAlway
  • 匹配中的冗余子句

    当我运行以下脚本时 Definition inv a Prop Prop match a with False gt True True gt False end 我收到 错误 该子句是多余的 知道为什么会发生这种情况吗 谢谢 马库斯 这件
  • 有没有办法禁用 Coq 中的特定符号?

    我希望在 Coqide 中 证明状态不使用某种符号 但仍使用所有其他符号 这可能吗 据我在文档中的理解 这是不可能的 您也许可以使用打开 关闭范围 但我不确定它是否有效 因为明确指出只要有可能 符号将用于打印
  • 引入先前证明的定理作为假设

    假设我已经在coq中证明了某个定理 稍后我想将其作为假设引入到另一个定理的证明中 有没有一种简洁的方法来做到这一点 当我想做一些诸如案例证明之类的事情时 我通常会出现这种需要 我发现做到这一点的一种方法是assert陈述定理 然后立即证明它
  • coqide - 无法从同一文件夹加载模块

    我无法加载 CoqIde 中同一文件夹中的模块 我正在尝试从 Software Foundations 加载源代码 我正在包含 SF 源代码的文件夹中运行 coqidecoqide or coqide 然后打开并运行该文件后 我收到此错误
  • Coq 中的程序定点和函数有什么区别?

    它们似乎有相似的目的 到目前为止我注意到的一个区别是Program Fixpoint将接受复合措施 例如 measure length l1 length l2 Function似乎拒绝这一点并且只会允许 measure length l1
  • 证明匹配语句

    为了解决一个练习 我有以下代表整数的定义 Inductive bin Type Zero bin Twice bin gt bin TwiceOne bin gt bin 这个想法是 Twice x is 2 x 两次一x is 2 x 1
  • 如何将假设中的具体变量更改为存在量化变量?

    假设我有一个这样的假设 FooProp a b 我想将假设改为这种形式 exists a FooProp a b 我怎样才能做到这一点 我知道我能做到assert exists a FooProp a b by eauto但我试图找到一个不
  • 在 Coq 中使用依赖类型(安全第 n 个函数)

    我正在尝试学习 Coq 但我发现很难从我读到的内容中实现飞跃软件基础 and 依赖类型的认证编程到我自己的用例 特别是 我想我应该尝试制作一个经过验证的版本nth列表上的函数 我设法写了这个 Require Import Arith Req
  • 如何暂时禁用 Coq 中的符号

    当您熟悉项目时 符号很方便 但当您刚刚开始使用代码库时 符号可能会令人困惑 我知道你可以用白话关闭所有符号Set Printing All 但是 我想保留一些打印 例如隐式参数 全部打印如下 Require Import Utf8 core
  • Coq - 在不丢失信息的情况下归纳函数

    当尝试对函数的结果 返回归纳类型 执行案例分析时 我在 Coq 中遇到了一些麻烦 当使用通常的策略时 比如elim induction destroy等等 信息就会丢失 我举个例子 我们首先有一个像这样的函数 Definition f n
  • 如何一步步检查 Coq 中更复杂的策略的作用?

    我试图经历那些著名的和精彩的软件基础书籍 https softwarefoundations cis upenn edu lf current Basics html lab30但我举了一个例子simpl and reflexivity 只
  • Coq 中的“错误:宇宙不一致”是什么意思?

    我正在努力通过软件基础 http www cis upenn edu bcpierce sf current 目前正在做教堂数字的练习 这是自然数的类型签名 Definition nat forall X Type X gt X gt X
  • 如何在构造微积分中提取Sigma的第二个元素?

    我尝试这样做 A gt B A gt gt t r gt x a gt B x gt r gt r gt t B t A x A gt y B x gt x x A gt y B x gt y 请注意 由于该函数返回的值取决于 sigma
  • Coq案例分析和函数返回子集类型的重写

    我正在做一个关于使用子集类型编写经过认证的函数的简单练习 想法是先写一个前驱函数 pred forall n n nat n gt 0 m nat S m n 1 然后使用这个定义给定一个函数 pred2 forall n n nat n

随机推荐