forall n m : nat, exists q : nat, exists r : nat, n = q * m + r
q
和r
构建合适的值m
和n
的方法。Fixpoint
并将其解压缩。我想仔细注意那个任务不是我在这里考虑的。甚至可以将我的证明中隐含的算法提取到Haskell中吗?如果有可能,会怎么做?
答案 0 :(得分:20)
感谢Prof. Pierce's summer 2012 video 4.1建议的Dan Feltey,我们看到关键是要提取的定理必须提供Type
的成员而不是通常的命题,这是Prop
。
对于特定定理,受影响的构造是归纳的Prop ex
及其符号exists
。与Pierce教授的工作类似,我们可以说明我们自己的替代定义ex_t
和exists_t
,用Prop
替换Type
的出现次数。
以下是ex
和exists
的常规重新定义,与Coq标准库中定义的类似。
Inductive ex (X:Type) (P : X->Prop) : Prop :=
ex_intro : forall (witness:X), P witness -> ex X P.
Notation "'exists' x : X , p" := (ex _ (fun x:X => p))
(at level 200, x ident, right associativity) : type_scope.
以下是其他定义。
Inductive ex_t (X:Type) (P : X->Type) : Type :=
ex_t_intro : forall (witness:X), P witness -> ex_t X P.
Notation "'exists_t' x : X , p" := (ex_t _ (fun x:X => p))
(at level 200, x ident, right associativity) : type_scope.
现在,有点不幸的是,有必要使用这些新定义重复定理的语句和证明。
世界上有什么?
为什么有必要对该定理进行重复陈述,并重复证明该定理,只有使用量词的替代定义才有区别?
我原本希望用
Prop
中的现有定理来证明Type
中的定理。当inversion
使用Prop
并且目标是Prop
使用{{}时,当Coq拒绝环境中exists
的证明策略Type
时,该策略失败{1}}。 Coq报告“错误:反转将需要对排序集进行案例分析,这是不允许的 对于归纳定义ex。“这种行为发生在Coq 8.3中。我不确定它 仍然出现在Coq 8.4中。我认为重复证据的必要性实际上是深刻的,尽管我怀疑我个人是否能够完全理解它的深刻性。它涉及的事实是
exists_t
是“不可预测的”而Prop
不是不可预测的,而是默认的“分层”。对于罗素的悖论,预测性是(如果我理解正确的话),那些不属于自己的集合的集合S既不是S的成员,也不是S的非成员。Type
默认避免罗素的悖论创建包含较低类型的较高类型的序列。因为Coq在Curry-Howard对应的公式 - 类型解释中被浸透,如果我正确得到这个,我们甚至可以理解Coq中类型的分层,以避免哥德尔不完整性,某些公式表达的现象对自己这样的公式的限制,从而对于他们的真实或谎言变得不可知。
回到地球上,这是使用“exists_t”的定理的重复陈述。
Type
由于我省略了Theorem divalg_t : forall n m : nat, exists_t q : nat,
exists_t r : nat, n = plus (mult q m) r.
的证明,我也会省略divalg
的证明。我只会提到我们确实有幸,包括“存在”和“反转”在内的证据策略与我们的新定义“ex_t”和“exists_t”的工作方式相同。
最后,提取本身很容易完成。
divalg_t
生成的Haskell文件包含许多定义,其核心是相当不错的代码,如下所示。我几乎完全不了解Haskell编程语言,只是略微受到了阻碍。请注意,Extraction Language Haskell.
Extraction "divalg.hs" divalg_t.
会创建类型为Ex_t_intro
的结果; Ex_t
和O
是Peano算术的零和后继函数; S
测试Peano数字的平等性; beq_nat
是一个高阶函数,它在参数中重复该函数。此处未显示nat_rec
的定义。无论如何,它是由Coq根据Coq。
nat_rec
更新2013-04-24:我现在知道更多Haskell了。为了帮助其他人阅读上面提取的代码,我提出了以下手写的代码,我认为这些代码是等效的,更具可读性。我还提出了我没有消除的提取定义Nat,O,S和nat_rec。
divalg :: Nat -> Nat -> Ex_t Nat (Ex_t Nat ())
divalg n m =
case m of {
O -> Ex_t_intro O (Ex_t_intro n __);
S m' ->
nat_rec (Ex_t_intro O (Ex_t_intro O __)) (\n' iHn' ->
case iHn' of {
Ex_t_intro q' hq' ->
case hq' of {
Ex_t_intro r' _ ->
let {k = beq_nat r' m'} in
case k of {
True -> Ex_t_intro (S q') (Ex_t_intro O __);
False -> Ex_t_intro q' (Ex_t_intro (S r') __)}}}) n}
答案 1 :(得分:1)
2012年7月25日的软件基础的最新版本在后面的章节“Extraction2”中非常简明扼要地回答了这个问题。答案是它肯定可以完成,就像这样:
Extraction Language Haskell
Extraction "divalg.hs" divalg
还需要一个技巧。 divalg必须是Prop
,而不是Type
。否则它将在提取过程中被删除。
哦,@Anthill是对的,我没有回答这个问题,因为我不知道如何解释皮尔斯教授是如何在他的Norm.v和MoreStlc.v的NormInType.v变体中完成的。< / p>
好的,无论如何,这是我的部分答案的其余部分。
如果上面出现“divalg”,则需要提供所有命题的空格分隔列表(必须将每个命题重新定义为Type
而不是Prop
) divalg依赖。有关证据提取的详尽,有趣且有效的示例,可以参考上面提到的章节Extraction2。该示例提取到OCaml,但是将其调整为Haskell只是使用上述Extraction Language Haskell
的问题。
在某种程度上,我花了一些时间不知道上述答案的原因是我一直在使用2010年10月14日我在2011年下载的软件基础的副本。