首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >归纳命题在Coq中是如何工作的?

归纳命题在Coq中是如何工作的?
EN

Stack Overflow用户
提问于 2018-12-16 22:49:56
回答 2查看 1.1K关注 0票数 5

我在软件基础和Adam的第4章书中读过IndProp,我很难理解归纳命题。

作为一个运行中的示例,让我们使用:

代码语言:javascript
运行
复制
Inductive ev : nat -> Prop :=
| ev_0 : ev 0
| ev_SS : forall n : nat, ev n -> ev (S (S n)).

我想我确实理解使用Set的“正常”类型,比如:

代码语言:javascript
运行
复制
Inductive nat : Set :=
  | O : nat
  | S : nat -> nat.

O这样的东西只返回nat类型的单个对象,S O接受一个nat类型的对象,并返回另一个,不同的,相同类型的nat中的一个。对于不同的对象,我想我的意思是它们有不同的价值。

我感到困惑的是,归纳道具的构造函数与归纳类型Set到底有什么不同。对于Set,它们似乎只是作为函数运行,这是一个接受值并返回更多该类型值的函数。但是对于归纳性命题,我很难弄清楚它们是做什么的。

例如,将ev_0作为一个简单的例子。我假定这是命题对象(值) ev 0的名称。由于ev 0本身就是一个Prop,所以它是一个命题。但究竟是什么让它成为现实呢?如果这是一个命题,我想这可能是错误的。我想这种归纳让我很困惑。ev是“返回某种类型的对象(命题)的函数”,因此ev 0只是一个命题,但是我们没有说ev 0应该是什么意思(与我对自然数的定义中的基本情况不同的是,它的作用是什么)。在蟒蛇身上我会看到

n == 0: return True

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

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

对于ev_SS来说,这更令人困惑。当然,由于我不知道标签在做什么,这让我很困惑,但是看看这是如何指出的:

代码语言:javascript
运行
复制
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中是如何工作的吗?

注意,我并不真正理解SetType之间的区别,但我相信这将是另一篇文章。

还有一些评论:

我还玩了几下然后做了:

代码语言:javascript
运行
复制
Check ev_SS

令我惊讶的是:

代码语言:javascript
运行
复制
ev_SS
     : forall n : nat, ev n -> ev (S (S n))

我认为这是意外的,因为我没想到ev_SS的类型(除非我误解了Check应该做的事情)是函数本身的定义。我认为ev_SS是一个构造函数,所以在我的脑海中,我认为它会执行映射,在本例中是nat -> Prop,所以,当然,这就是我所期望的类型。

EN

回答 2

Stack Overflow用户

发布于 2018-12-17 01:41:41

因此,首先,这是正常的,你会对此感到困惑,但它可能比你想的更简单!

有两个不同的概念,你很困惑,所以让我们一次一个。首先,您提到ev 0是一个命题,并想知道是什么使其成为现实。您将在某一时刻了解到命题和类型是相同的,PropSetType之间的区别并不是这些事物本质上是不同的。

因此,当您定义类型(或命题) nat时,您将创建一个新类型,并描述其中存在的值。您可以声明有一个值O,即nat。并声明在传递一个S时,存在一个参数化值nat,即nat

同样,当您定义类型(或命题) ev时,您将创建一个新类型(实际上,它是由nat类型的值索引的类型系列),并描述这些ev类型中存在的值。您可以声明有一个值ev_0,即ev 0。并声明在传递一个ev_SS和一个ev n时,存在一个参数化的值n : nat,即ev (S (S n))

因此,you通过在其中创建价值的方法使这一命题成为现实。还可以通过没有构造函数或具有永远无法调用的构造函数来定义错误命题:

代码语言:javascript
运行
复制
Inductive MyFalse1 := . (* no constructor! *)

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

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

现在,关于事物的命名,ev_0ev_SSOS都是相同类型的实体:构造函数。我不知道为什么您认为ev_0是指向值ev 0的指针。

ev n作为一个命题分配没有任何意义,但如果有一种使用ev n类型构造值的方法,则它可能是正确的;如果无法用ev n类型构造值,则可能是假的。

但是,请注意,ev n是精心构建的,为那些偶数的n而设,而对于那些奇怪的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))
  • 等。

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

Prop支持代码生成的优化。对于程序员来说,这基本上是一种将某些类型标记为仅用于验证目的,而不是用于计算目的的方法。结果,类型检查器将迫使您永远不计算Prop宇宙中的证明,代码生成将知道它可以丢弃这些证明,因为它们不参与计算行为。

Set只是Prop的一个限制,以避免处理宇宙级别。在以后的学习过程中,你不需要真正理解这一点。

你真的应该尽量不要把Prop看作是一个与Set不同的神奇事物。

以下内容可能对您有所帮助:我们可以以完全相同的方式重写natev的定义,如下所示:

代码语言:javascript
运行
复制
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)编写ev_SS的原因是我们有为第一个参数命名,因为第二个参数的类型将取决于它(第二个参数具有ev n类型)。

票数 8
EN

Stack Overflow用户

发布于 2018-12-17 07:32:51

如果您用Prop替换为Set,那么您就会说您理解这个定义:

代码语言:javascript
运行
复制
Inductive ev' : nat -> Set :=
| ev_0' : ev' 0
| ev_SS' : forall n : nat, ev' n -> ev' (S (S n)).

对于每一个n : nat,我们都认为ev' n是一种有一些元素的类型,或者没有。因为这是一个归纳定义,我们可以知道ev' 0的元素是什么:惟一的元素是ev_0' (或者更准确地说,ev' 0类型的每一个封闭项都计算到ev_0;)。ev_0 1没有任何元素,但是有一个ev 2'元素,即ev_SS' 0 ev_0'。事实上,有一点思考表明,ev n要么是空的,要么是单例的,这取决于n是偶数还是奇数。

当我们从Set切换到Prop时,情况完全一样,只是读取方式不同:Set是(大型)类型,Prop也是类型(它们是宇宙)。Prop的每个元素都是一个类型(但我们更喜欢称之为“命题”),它有一些元素(但我们更愿意称它们为“证明”)。因此,请考虑一下:

代码语言:javascript
运行
复制
Inductive ev : nat -> Prop :=
| ev_0 : ev 0
| ev_SS : forall n : nat, ev n -> ev (S (S n)).

对于每一个n : nat,我们都认为ev n是一个语句,即n拥有属性ev,不管该属性是什么。对于任何给定的n,可能都有ev n的证明,在这种情况下,n具有属性ev,或者没有这样的证明,在这种情况下,n没有属性ev。因为这是一个归纳定义,我们可以知道ev_0的证明是什么:它们都计算到ev_0'。没有ev_0 1的证明,但有ev 2的证明,即ev_SS 0 ev_0。事实上,一点点思考表明,ev n有一个证明当且仅当n是偶数的。我们现在了解到,ev是“偶数”的属性。

这就是所谓的“作为类型的命题”。

我们观察到ev' 0只包含一个元素ev_0'。类型unit也只包含一个元素tt。这是否意味着ev' 0unit是相等的?不,但它们是等价的,因为我们可以提供函数ev' 0 -> unitunit -> ev' 0,它们是相互逆的。

对于ev 0,我们可以问同样的问题:它是否等于True?不,但它们是等价的,因为我们可以证明ev 0 -> TrueTrue -> ev' 0的含义。

人们开始怀疑PropSet之间有什么区别。对于一个类型的P : Prop,它的所有元素都被认为是相等的,也就是说,Coq不允许我们区分它们。(这是一个教学上的谎言,因为在现实中,Coq对于P中的所有元素是否都被认为是平等的是不可知的,但也许最好现在就不要讨论这个问题。)

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53807156

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档