我可以将 Coq 证明提取为 Haskell 函数吗?

2024-04-25

  • 自从学了一点 Coq 以来,我就想学着写一个所谓的除法算法的 Coq 证明,它实际上是一个逻辑命题:forall n m : nat, exists q : nat, exists r : nat, n = q * m + r
  • 我最近利用我学到的知识完成了这项任务软件基础 http://www.cis.upenn.edu/~bcpierce/sf/.
  • Coq 是一个用于开发构造性证明的系统,我的证明实际上是一种构造合适值的方法q and r从价值观m and n.
  • Coq 有一个有趣的工具,可以将 Coq 算法语言 (Gallina) 中的算法“提取”到包括 Haskell 在内的通用函数编程语言。
  • 另外,我设法将 divmod 操作编写为 GallinaFixpoint并提取它。我想仔细指出,该任务不是我在这里考虑的。
  • 亚当·奇利帕拉 (Adam Chlipala) 曾在依赖类型的认证编程 http://adam.chlipala.net/cpdt/“许多 Curry-Howard 通信的粉丝支持从证明中提取程序的想法。实际上,很少有 Coq 和相关工具的用户会这样做。”

是否有可能提取我对 Haskell 的证明中隐含的算法?如果可以的话,会怎样做呢?


谢谢Pierce教授2012年夏季视频4.1 http://www.cs.uoregon.edu/Research/summerschool/summer12/curriculum.html as 丹·费尔蒂 https://stackoverflow.com/users/1447178/dan-feltey建议,我们看到关键是要提取的定理必须提供一个成员Type而不是通常的命题,即Prop.

对于特定定理,受影响的构造是归纳 Propex及其符号exists。与皮尔斯教授所做的类似,我们可以陈述我们自己的替代定义ex_t and exists_t替换出现的Prop与出现Type.

这是通常的重新定义ex and 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。当 Coq 拒绝证明策略时,该策略失败inversion for a Prop当那个环境中Prop uses exists目标是Type使用exists_t。 Coq 报告“错误:反转需要对排序集进行案例分析,这是不允许的 对于归纳定义例如。”这种行为发生在 Coq 8.3 中。我不确定它是否是这样 在 Coq 8.4 中仍然出现。

我认为重复证明的必要性实际上是深刻的,尽管我怀疑我个人是否能够理解其深刻性。它涉及以下事实:Prop是“必然的”并且Type不是强制性的,而是默认的“分层”。预测性(如果我理解正确的话)是罗素悖论的弱点,即非自身成员的集合组成的集合 S 既不能是 S 的成员,也不能不是 S 的成员。Type通过默认创建一系列包含较低类型的较高类型来避免罗素悖论。因为 Coq 充分体现了 Curry-Howard 对应关系的公式即类型解释,如果我理解正确,我们甚至可以将 Coq 中的类型分层理解为避免哥德尔不完备性(某些公式所表达的现象)的一种方法对公式本身的限制,从而使其真假变得不可知。

回到地球,这里是使用“exists_t”重复陈述该定理。

Theorem divalg_t : forall n m : nat, exists_t q : nat,
  exists_t r : nat, n = plus (mult q m) r.

由于我省略了证明divalg,我也会省略证明divalg_t。我只会提到,我们确实很幸运,包括“存在”和“反演”在内的证明策略与我们的新定义“ex_t”和“exists_t”的工作原理相同。

最后,提取本身很容易完成。

Extraction Language Haskell.

Extraction "divalg.hs" divalg_t.

生成的 Haskell 文件包含许多定义,其核心是下面相当不错的代码。我对 Haskell 编程语言几乎完全无知,这只是稍微妨碍了我。注意Ex_t_intro创建一个类型为的结果Ex_t; O and S是皮亚诺算术中的零和后继函数;beq_nat测试皮亚诺数是否相等;nat_rec是一个高阶函数,在其参数中的函数上递归。的定义nat_rec此处未显示。无论如何,它是由 Coq 根据 Coq 中定义的归纳类型“nat”生成的。

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}

2013-04-24 更新:我现在对 Haskell 有了更多了解。为了帮助其他人阅读上面提取的代码,我提供了以下手写代码,我认为这些代码是等效的并且更具可读性。我还展示了我没有消除的提取定义 Nat、O、S 和 nat_rec。

-- Extracted: Natural numbers (non-negative integers)
-- in the manner in which Peano defined them.
data Nat =
   O
 | S Nat
   deriving (Eq, Show)

-- Extracted: General recursion over natural numbers,
-- an interpretation of Nat in the manner of higher-order abstract syntax.
nat_rec :: a1 -> (Nat -> a1 -> a1) -> Nat -> a1
nat_rec f f0 n =
  case n of {
   O -> f;
   S n0 -> f0 n0 (nat_rec f f0 n0)}

-- Given non-negative integers n and m, produce (q, r) with n = q * m + r.
divalg_t :: Nat -> Nat -> (Nat, Nat)
divalg_t n      O = (O, n)      -- n/0: Define quotient 0, remainder n.
divalg_t n (S m') = divpos n m' -- n/(S m')
  where
        -- Given non-negative integers  n and m',
        -- and defining m = m' + 1,
        -- produce (q, r) with n = q * m + r
        -- so that q = floor (n / m) and r = n % m.
        divpos :: Nat -> Nat -> (Nat, Nat)
        divpos n m' = nat_rec (O, O) (incrDivMod m') n
        -- Given a non-negative integer m' and
        -- a pair of non-negative integers (q', r') with r <= m',
        -- and defining m = m' + 1,
        -- produce (q, r) with q*m + r = q'*m + r' + 1 and r <= m'.
        incrDivMod :: Nat -> Nat -> (Nat, Nat) -> (Nat, Nat)
        incrDivMod m' _ (q', r')
          | r' == m'  = (S q', O)
          | otherwise = (q', S r')
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

我可以将 Coq 证明提取为 Haskell 函数吗? 的相关文章

  • 当目标是类型时,为什么 Coq 不允许反转、析构等?

    When refine正在运行一个程序 我试图通过以下方式结束证明inversion on a False假设当目标是Type 这是我尝试做的证明的简化版本 Lemma strange1 forall T Type 0 gt 0 gt T
  • 如何证明 Coq 中的两个 Fibonacci 实现相等?

    我有两个斐波那契实现 如下所示 我想证明它们在功能上是等效的 我已经证明了自然数的性质 但是这个练习需要另一种我无法弄清楚的方法 我使用的教科书介绍了 Coq 的以下语法 因此应该可以使用这种表示法来证明相等性
  • 如何切换到 Coq 的特定版本——尤其是在使用 Opam 管理 Coq 版本时?

    我目前使用的是标准方式 可能通过网站 安装的标准方式 但我想用tcoq 我相信我已经正确安装了它 因为我有一个 bin 文件 并且所有常见的 Coq 内容似乎都在那里 pinno gamepad tcoq ls bin coq tex co
  • Coq 平等实现

    我正在编写一种玩具语言 其中 AST 中的节点可以有任意数量的子节点 Num has 0 Arrow有 2 个 等等 您可以致电这些接线员 此外 AST 中可能只有一个节点被 聚焦 我们对数据类型进行索引Z如果它有焦点 或者H如果没有 我需
  • Coq:定义子类型

    我有一个类型 比如说 Inductive Tt a b c 定义它的子类型的最简单和 或最好的方法是什么 假设我希望子类型仅包含构造函数a and b 一种方法是对二元素类型进行参数化 例如布尔 Definition filt x bool
  • 匹配中的冗余子句

    当我运行以下脚本时 Definition inv a Prop Prop match a with False gt True True gt False end 我收到 错误 该子句是多余的 知道为什么会发生这种情况吗 谢谢 马库斯 这件
  • 引入先前证明的定理作为假设

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

    我无法加载 CoqIde 中同一文件夹中的模块 我正在尝试从 Software Foundations 加载源代码 我正在包含 SF 源代码的文件夹中运行 coqidecoqide or coqide 然后打开并运行该文件后 我收到此错误
  • 证明匹配语句

    为了解决一个练习 我有以下代表整数的定义 Inductive bin Type Zero bin Twice bin gt bin TwiceOne bin gt bin 这个想法是 Twice x is 2 x 两次一x is 2 x 1
  • 在 Coq 中,重写适用于 = 但不适用于 <-> (iff)

    我在证明期间有以下内容 我需要替换normal form step t with value t因为有一个已证明的定理存在等价 H1 t1 gt t1 normal form step t1 t2 tm H2 t2 gt t2 normal
  • 如何在 Coq 中禁用我的自定义符号?

    我定义了一个符号来模拟命令式编程 Notation a gt gt b b a at level 50 然而之后 所有函数应用表达式都表示为 gt gt 样式 例如 在 Coq Toplevel 的证明模式下 我可以看到 bs nat gt
  • 如何在 Coq 简化过程中应用一次函数?

    据我了解 Coq 中的函数调用是不透明的 有时 我需要使用unfold应用它然后fold将函数定义 主体恢复为其名称 这通常很乏味 我的问题是 是否有更简单的方法来应用函数调用的特定实例 作为一个最小的例子 对于一个列表l 证明右附加 没有
  • Coqide 错误:编译的库 Basics.vo 对库做出了不一致的假设

    我在 mac os X 上使用 CoqIDE 8 4pl5 当 CoqIDE 转发到此命令时 会弹出此错误消息 需要导入基础知识 错误 编译的库 Basics vo 对库做出了不一致的假设 Coq Init Notifications 当我
  • 逻辑:tr_rev_ Correct 的辅助引理

    在逻辑章节中 介绍了反向列表函数的尾递归版本 我们需要证明它可以正确工作 Fixpoint rev append X l1 l2 list X list X match l1 with gt l2 x l1 gt rev append l1
  • Coq - 在不丢失信息的情况下归纳函数

    当尝试对函数的结果 返回归纳类型 执行案例分析时 我在 Coq 中遇到了一些麻烦 当使用通常的策略时 比如elim induction destroy等等 信息就会丢失 我举个例子 我们首先有一个像这样的函数 Definition f n
  • 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 中的特定值?

    我正在尝试实现一个函数 该函数可以简单地计算包中某些 nat 的出现次数 只是列表的同义词 这就是我想做的 但它不起作用 Require Import Coq Lists List Import ListNotations Definiti
  • 在 Coq 中,“if then else”允许非布尔第一个参数?

    我读过一些教程if a then b else c代表match a with true gt b false gt c end 然而 很奇怪的是 前者不检查类型a 而后者当然确保a是一个布尔值 例如 Coq lt Check if nil
  • 在 Coq 模块系统中导入 与包含

    确切的语义是什么Include M1在另一个模块中 比如 M 这与做有什么不同Import M1在模块 M 内 更准确地说 以下命令的语义是什么 Module Type M M1 lt M2 lt M3 总结这两个白话命令的语义 命令Inc

随机推荐