为什么较新的依赖类型语言没有采用 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 的方法? 的相关文章

  • 在 Idris 中证明如果 n = m 且 m = o,则 n + m = m + o?

    我正在尝试通过查看一些练习来提高我的伊德里斯技能软件基础 https softwarefoundations cis upenn edu lf current toc html 最初是为 Coq 设计的 但我希望对 Idris 的翻译不会太
  • 如何在 Coq 中禁用我的自定义符号?

    我定义了一个符号来模拟命令式编程 Notation a gt gt b b a at level 50 然而之后 所有函数应用表达式都表示为 gt gt 样式 例如 在 Coq Toplevel 的证明模式下 我可以看到 bs nat gt
  • 为什么不采用依赖类型呢?

    我看到几个消息来源都赞同 Haskell 正在逐渐成为一种依赖类型的语言 的观点 这似乎意味着 随着越来越多的语言扩展 Haskell 正在朝着这个大方向漂移 但还没有实现 基本上有两件事我想知道 第一个很简单 成为一种依赖类型的语言 实际
  • 如何将假设中的具体变量更改为存在量化变量?

    假设我有一个这样的假设 FooProp a b 我想将假设改为这种形式 exists a FooProp a b 我怎样才能做到这一点 我知道我能做到assert exists a FooProp a b by eauto但我试图找到一个不
  • 在 Agda 中对 ST monad 进行建模

    最近这个所以问题 https stackoverflow com questions 33975270 can a st like monad be executed purely without the st library促使我在 Ha
  • 将排序列表与大小类型合并

    假设我们有一个排序列表的数据类型 具有与证明无关的排序见证 我们将使用 Agda 的实验性大小类型功能 这样我们就有希望在数据类型上获得一些递归函数来通过 Agda 的终止检查器 OPTIONS sized types open impor
  • 理解 `k : Nat ** 5 * k = n` 签名

    以下函数编译 onlyModByFive n Nat gt k Nat 5 k n gt Nat onlyModByFive n k 100 但有什么作用k以其代表Nat 5 k n syntax 另外 我该如何称呼它 这是我尝试过的 但我
  • 使用标准库对 Agda 中的对/列表进行字典顺序排序

    Agda标准库包含一些模块Relation Binary Non StrictLex 目前仅适用于Product and List 我们可以使用这些模块轻松构建一个实例 例如IsStrictTotalOrder对于自然数对 即 open i
  • Coq 中的 Modus Ponens 和 Modus Tollens

    我想要针对这些简单的推理规则使用 Ltac 策略 在 Modus Ponens 中 如果我有H P gt Qand H1 P Ltac mp H H1将添加Q到上下文为H2 Q 在 Modus Tollens 中 如果我有H P gt Qa
  • 消除subst来证明平等

    我试图将 mod n 计数器表示为间隔的一部分 0 n 1 分为两部分 data Counter Set where cut i j Counter suc i j 使用它 定义两个关键操作很简单 为简洁起见 省略了一些证明 1 n Cou
  • 如何学习阿格达

    我正在努力学习agda 但是 我遇到了一个问题 我在 agda wiki 上找到的所有教程对我来说都太复杂了 并且涵盖了编程的不同方面 在并行阅读了 3 个关于 agda 的教程后 我能够编写简单的证明 但我仍然没有足够的知识来使用它来实现
  • AGDA 中极浅嵌入 VHDL 的指南

    对于我的编程语言项目 我正在 agda 中做一个非常浅且简单的 VHDL 数字电路嵌入 目的是写出语法 静态语义 动态语义 然后写一些证明来展示我们对材料的理解 到目前为止我已经编写了以下代码 data Ckt Set where var
  • Coq案例分析和函数返回子集类型的重写

    我正在做一个关于使用子集类型编写经过认证的函数的简单练习 想法是先写一个前驱函数 pred forall n n nat n gt 0 m nat S m n 1 然后使用这个定义给定一个函数 pred2 forall n n nat n
  • Agda 中的递归方案

    不用说 Haskell 中的标准构造 newtype Fix f Fix getFix f Fix f cata Functor f gt f a gt a gt Fix f gt a cata f f fmap cata f getFix
  • Idris - 在 n 维向量上映射操作

    我在 Idris 中定义 n 维向量如下 import Data Vect NDVect Num t gt rank Nat gt shape Vect rank Nat gt t Type gt Type NDVect Z t t NDV
  • 我如何编写行为类似于“破坏...作为”的策略?

    在coq中 destruct https coq inria fr distrib current refman Reference Manual010 html hevea tactic65策略有一个接受 连接析取引入模式 的变体 该模式
  • 如何处理 Coq 中 Program Fixpoint 生成的非常大的项?

    我试图在 Coq 中定义并证明正确的函数 该函数可以有效地比较两个排序列表 由于它并不总是在结构较小的项上递归 第一个或第二个列表较小 Fixpoint不会接受它 所以我尝试使用Program Fixpoint反而 当尝试使用策略证明函数的
  • Agda 中实例参数的问题

    我正在尝试遵循 McBride s 的代码如何维持邻居秩序 https personal cis strath ac uk conor mcbride pub Pivotal pdf 并且无法理解为什么 Agda 我正在使用 Agda 2
  • 在 Idris 中,我可以证明自由定理吗? `forall t 类型的唯一(全部)函数。 t -> t` 是 `id`?

    对于足够多态的类型 参数性可以唯一地确定函数本身 参见瓦德勒的定理免费 http www cs sfu ca CourseCentral 831 burton Notes July14 free pdf了解详情 例如 唯一具有类型的总函数f
  • Coq:多个构造函数的单一表示法

    是否可以在 Coq 中为多个构造函数定义单一符号 如果构造函数的参数类型不同 则可以从中推断出它们 一个最小的 非 工作示例 Inductive A Set a b c C gt A d D gt A with C Set c1 c2 wi

随机推荐