为什么较新的依赖类型语言没有采用 SSReflect 的方法?

2024-04-24

我在 Coq 的 SSReflect 扩展中发现了两个约定,它们似乎特别有用,但我还没有看到它们在较新的依赖类型语言(Lean、Agda、Idris)中得到广泛采用。

首先,可能的谓词被表示为布尔返回函数而不是归纳定义的数据类型。默认情况下,这带来了可判定性,为计算证明提供了更多机会,并通过避免证明引擎携带大量证明项来提高检查性能。我看到的主要缺点是在证明时需要使用反射引理来操作这些布尔谓词。

其次,具有不变量的数据类型被定义为包含简单数据类型加上不变量证明的依赖记录。例如,固定长度序列在 SSReflect 中定义如下:

Structure tuple_of : Type := Tuple {tval :> seq T; _ : size tval == n}.

A seq以及该序列长度为某个值的证明。这与例如如何Idris 定义了这种类型:

data Vect : (len : Nat) -> (elem : Type) -> Type 

一种依赖类型的数据结构,其中不变量是其类型的一部分。 SSReflect 方法的优点之一是它允许重用,因此例如为seq关于它们的证明仍然可以使用tuple(通过对底层进行操作seq),而伊德里斯的方法函数如下reverse, append等等需要重写Vect。 Lean 实际上在其标准库中具有等效的 SSReflect 风格,vector,但它也有伊德里斯风格array这似乎在运行时有一个优化的实现。

One SSReflect 导向书籍 http://ilyasergey.net/pnp/pnp.pdf甚至声称Vect n A样式方法是一种反模式:

依赖类型语言(尤其是 Coq)中的一个常见反模式是将此类代数属性编码到数据类型和函数本身的定义中(一个典型的例子) 这种方法的主要特征是长度索引列表)。虽然这种方法看起来很吸引人,但正如它所证明的那样 依赖类型捕获数据类型及其函数的某些属性的能力,它 本质上是不可扩展的,因为总会有另一个感兴趣的属性,而该属性尚未被扩展 由数据类型/函数的设计者预见到,因此必须将其编码为外部事实 反正。这就是为什么我们提倡这种方法,其中数据类型和函数被定义为接近的 程序员尽可能定义它们的方式,以及它们的所有必要属性 分别证明。

因此,我的问题是,为什么这些方法没有被更广泛地采用。我是否遗漏了一些缺点,或者它们的优点在比 Coq 更好地支持依赖模式匹配的语言中可能不太重要?


我可以就第一点(将谓词定义为布尔返回函数)提供一些想法。我对这种方法的最大问题是:那么根据定义,该函数不可能有错误,即使事实证明它正在计算的内容不是您想要计算的内容。在许多情况下,如果必须在谓词的定义中包含谓词的决策过程的实现细节,它也会模糊谓词的实际含义。

在数学应用中,如果您想要定义一个谓词,该谓词是一般不可判定的事物的特化,即使它在您的特定情况下恰好是可判定的,也会出现问题。我在这里讨论的一个例子是用给定的表示来定义组:在 Coq 中,定义它的一种常见方法是 setoid,其底层集合是生成器中的形式表达式,并且由“word”给出的等式等价”。一般来说,这种关系是不可判定的,尽管在许多特定情况下是可判定的。然而,如果您仅限于用单词问题可判定的表示来定义组,那么您就失去了定义将所有不同示例联系在一起的统一概念的能力,并且无法一般性地证明有关有限表示或有限表示组的事物。另一方面,将等价关系一词定义为抽象的Prop或同等内容很简单(如果可能有点长)。

就我个人而言,我更喜欢首先给出谓词的最透明的可能定义,然后在可能的情况下提供决策过程(返回类型值的函数{P} + {~P}是我在这里的偏好,尽管布尔返回函数也可以很好地工作)。 Coq 的类型类机制可以提供一种便捷的方式来注册此类决策过程;例如:

Class Decision (P : Prop) : Set :=
decide : {P} + {~P}.
Arguments decide P [Decision].

Instance True_dec : Decision True := left _ I.
Instance and_dec (P Q : Prop) `{Decision P} `{Decision Q} :
  Decision (P /\ Q) := ...

(* Recap standard library definition of Forall *)
Inductive Forall {A : Type} (P : A->Prop) : list A -> Prop :=
| Forall_nil : Forall P nil
| Forall_cons : forall h t, P h -> Forall P t -> Forall P (cons h t).
(* Or, if you prefer:
Fixpoint Forall {A : Type} (P : A->Prop) (l : list A) : Prop :=
match l with
| nil => True
| cons h t => P h /\ Forall P t
end. *)

Program Fixpoint Forall_dec {A : Type} (P : A->Prop)
  `{forall x:A, Decision (P x)} (l : list A) :
  Decision (Forall P l) :=
  match l with
  | nil => left _ _
  | cons h t => if decide (P h) then
                  if Forall_dec P t then
                    left _ _
                  else
                    right _ _
                else
                  right _ _
  end.
(* resolve obligations here *)
Existing Instance Forall_dec.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么较新的依赖类型语言没有采用 SSReflect 的方法? 的相关文章

  • 如何实现参数化元组的“Show”接口?

    I have Coord将 n 维大小转换为给定大小限制的坐标类型的函数 Coord 2 3 Fin 2 Fin 3 import Data Fin import Data List Size Type Size List Nat Coor
  • 如何在 Coq 中切换当前目标?

    是否可以切换当前目标或子目标来在 Coq 中进行证明 例如 我有一个这样的目标 来自 eexists 1 1 s gt 0 r1 r1 s1 s r3 r3 s2 我想做的是split并首先证明正确的连接 我认为这将给出存在变量的值 s 并
  • 专门构造函数上的模式匹配

    这几天我一直在为一个问题绞尽脑汁 但我的 Agda 技能不是很强 我正在尝试在仅在特定索引处定义的索引数据类型上编写一个函数 这仅适用于数据构造函数的某些专门化 我不知道如何定义这样的函数 我试图将我的问题简化为一个更小的例子 该设置涉及自
  • F# 中的命令式多态性

    OCaml 的 Hindley Milner 类型系统不允许命令式多态性 类似于 System F 除非通过最近对记录类型的扩展 这同样适用于 F 然而 有时需要将用命令式多态性 例如 Coq 编写的程序翻译成此类语言 Coq 的 OCam
  • 在Refl中使用重写

    我正在使用 Idris 学习第 8 章类型驱动开发 我有一个关于 rewrite 如何与 Refl 交互的问题 此代码作为重写如何在表达式上工作的示例显示 myReverse Vect n elem gt Vect n elem myRev
  • 将假设中的 ~exists 转换为 forall

    我陷入了假设的境地 exists k k lt n 1 f k f n 2 并希望将其转换为等效的 我希望如此 假设forall k k lt n 1 gt f k lt gt f n 2 这是一个小例子 Require Import Co
  • 我可以在“coqtop - nois”下定义策略吗?

    coqtop nois Welcome to Coq 8 7 0 October 2017 Coq lt Ltac i idtac Toplevel input characters 0 4 gt Ltac i idtac gt Error
  • Coq :> 符号

    这可能是非常微不足道的 但我找不到任何关于 gt 符号在 Coq 中含义的信息 有什么区别 U 类型 和 W gt 类型 这取决于符号出现的位置 例如 如果它位于记录声明内 它会指示 Coq 添加相应的记录投影作为强制 具体来说 假设我们有
  • Coq:添加“强归纳”策略

    对自然数的 强 或 完全 归纳意味着当证明 n 上的归纳步骤时 您可以假设该属性对于任何 k 都成立 Theorem strong induction forall P nat gt Prop forall n nat forall k n
  • 可以在 Coq 的蕴涵中使用 destruct 吗?

    destruct可以用来分割and or在柯克 不过好像也可以用暗示 例如我想证明 P gt P Lemma test P P gt P Proof unfold not intro pffpf apply pffpf intro pff
  • 为什么在这种情况下重写不改变表达式的类型?

    在 1 中可以阅读下一篇 rewrite prf in expr 如果我们有prf x y 并且 expr 所需的类型是以下属性x the rewrite in语法将搜索x在所需的类型中expr并将其替换为y 现在 我有下一段代码 您可以将
  • 为什么coq互感类型必须具有相同的参数?

    下列的亚瑟的建议 https stackoverflow com a 17304209 403875 我改变了我的Fixpoint相互关系Inductive这种关系 建立 游戏之间的不同比较 而不是 深入研究 但现在我收到一条全新的错误消息
  • 约束接口中的函数参数

    在接受函数的接口中约束函数参数的语法是什么 我试过 interface Num a gt Color f a gt Type where defs 但它说Name a is not bound in interface Your inter
  • 我如何编写行为类似于“破坏...作为”的策略?

    在coq中 destruct https coq inria fr distrib current refman Reference Manual010 html hevea tactic65策略有一个接受 连接析取引入模式 的变体 该模式
  • Agda 中实例参数的问题

    我正在尝试遵循 McBride s 的代码如何维持邻居秩序 https personal cis strath ac uk conor mcbride pub Pivotal pdf 并且无法理解为什么 Agda 我正在使用 Agda 2
  • 证明后继者对等式的替代性质

    我试图理解归纳类型 精益中的定理证明 第 7 章 https leanprover github io theorem proving in lean 07 Inductive Types html 我给自己设定了一个任务 证明自然数的后继
  • 在 Coq 模块系统中导入 与包含

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

    我试图弄清楚类型层次结构在 Agda 中是如何工作的 假设我定义了一个集合类型X X Set 然后继续构建归纳类型 data Y X gt Set where 是什么类型的X gt Set 是设置还是类型 谢谢你 那么 为什么不问问 Agd
  • 为什么逻辑连接词和布尔值在 Coq 中是分开的?

    我有 JavaScript Ruby 编程背景 并且习惯了 true false 的工作方式 在 JS 中 true false false true 然后你可以使用这些真 假值 like var a true b false a b So
  • Coq:承认断言

    有没有办法在 Coq 中承认断言 假设我有一个这样的定理 Theorem test forall m n nat m n n m Proof intros n m assert H1 m m n m S n Admitted Abort 上

随机推荐