我在软件基础和Adam的第4章书中读过IndProp,我很难理解归纳命题。
作为一个运行中的示例,让我们使用:
Inductive ev : nat -> Prop :=
| ev_0 : ev 0
| ev_SS : forall n : nat, ev n -> ev (S (S n)).
我想我确实理解使用Set
的“正常”类型,比如:
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
来说,这更令人困惑。当然,由于我不知道标签在做什么,这让我很困惑,但是看看这是如何指出的:
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
与Type
之间的区别,但我相信这将是另一篇文章。
还有一些评论:
我还玩了几下然后做了:
Check ev_SS
令我惊讶的是:
ev_SS
: forall n : nat, ev n -> ev (S (S n))
我认为这是意外的,因为我没想到ev_SS
的类型(除非我误解了Check
应该做的事情)是函数本身的定义。我认为ev_SS
是一个构造函数,所以在我的脑海中,我认为它会执行映射,在本例中是nat -> Prop
,所以,当然,这就是我所期望的类型。
发布于 2018-12-17 01:41:41
因此,首先,这是正常的,你会对此感到困惑,但它可能比你想的更简单!
有两个不同的概念,你很困惑,所以让我们一次一个。首先,您提到ev 0
是一个命题,并想知道是什么使其成为现实。您将在某一时刻了解到命题和类型是相同的,Prop
和Set
与Type
之间的区别并不是这些事物本质上是不同的。
因此,当您定义类型(或命题) nat
时,您将创建一个新类型,并描述其中存在的值。您可以声明有一个值O
,即nat
。并声明在传递一个S
时,存在一个参数化值nat
,即nat
。
同样,当您定义类型(或命题) ev
时,您将创建一个新类型(实际上,它是由nat
类型的值索引的类型系列),并描述这些ev
类型中存在的值。您可以声明有一个值ev_0
,即ev 0
。并声明在传递一个ev_SS
和一个ev n
时,存在一个参数化的值n : nat
,即ev (S (S n))
。
因此,you通过在其中创建价值的方法使这一命题成为现实。还可以通过没有构造函数或具有永远无法调用的构造函数来定义错误命题:
Inductive MyFalse1 := . (* no constructor! *)
Inductive MyFalse2 :=
| TryToConstructMe : False -> MyFalse2
| ThisWontWorkEither : 0 = 1 -> MyFalse2
.
我现在已经声明了两种类型(或命题),但是没有办法证明它们,因为它们要么没有构造函数,要么就无法调用这些构造函数。
现在,关于事物的命名,ev_0
、ev_SS
、O
和S
都是相同类型的实体:构造函数。我不知道为什么您认为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)
)最后,对于Set
、Prop
和Type
之间的区别,这些都是您可以在其中创建归纳类型的宇宙,但它们都有一定的限制。
Prop
支持代码生成的优化。对于程序员来说,这基本上是一种将某些类型标记为仅用于验证目的,而不是用于计算目的的方法。结果,类型检查器将迫使您永远不计算Prop
宇宙中的证明,代码生成将知道它可以丢弃这些证明,因为它们不参与计算行为。
Set
只是Prop
的一个限制,以避免处理宇宙级别。在以后的学习过程中,你不需要真正理解这一点。
你真的应该尽量不要把Prop
看作是一个与Set
不同的神奇事物。
以下内容可能对您有所帮助:我们可以以完全相同的方式重写nat
和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)
编写ev_SS
的原因是我们有为第一个参数命名,因为第二个参数的类型将取决于它(第二个参数具有ev n
类型)。
发布于 2018-12-17 07:32:51
如果您用Prop
替换为Set
,那么您就会说您理解这个定义:
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
的每个元素都是一个类型(但我们更喜欢称之为“命题”),它有一些元素(但我们更愿意称它们为“证明”)。因此,请考虑一下:
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' 0
和unit
是相等的?不,但它们是等价的,因为我们可以提供函数ev' 0 -> unit
和unit -> ev' 0
,它们是相互逆的。
对于ev 0
,我们可以问同样的问题:它是否等于True
?不,但它们是等价的,因为我们可以证明ev 0 -> True
和True -> ev' 0
的含义。
人们开始怀疑Prop
和Set
之间有什么区别。对于一个类型的P : Prop
,它的所有元素都被认为是相等的,也就是说,Coq不允许我们区分它们。(这是一个教学上的谎言,因为在现实中,Coq对于P
中的所有元素是否都被认为是平等的是不可知的,但也许最好现在就不要讨论这个问题。)
https://stackoverflow.com/questions/53807156
复制相似问题