我证明了一些关于列表的定理,并从中提取了算法。现在我想使用堆,因为查找和连接更快。我目前要做的是只为提取的列表类型使用自定义定义。我想以更正式的方式做到这一点,但理想情况下无需重做我的所有证据。可以说我有一个类型
Heap : Set -> Set
和同构
f : forall A, Heap A -> List A.
此外,我有函数H_app和H_nth,这样
H_app (f a) (f b) = f (a ++ b)
和
H_nth (f a) = nth a
一方面,我必须用模仿列表递归的专用函数替换每个列表递归。另一方面,事先我希望将++
和nth
替换为H_app
和H_nth
,因此提取的算法会更快。问题是我在某些地方使用simpl
和compute
等策略,如果我只是替换证明代码中的所有内容,这可能会失败。之后有可能“重载”这些函数会很好。
这样的事情可能吗?
编辑:为了澄清,数字出现了类似的问题:我有一些使用nat
的旧证明,但数字太大了。使用BinNat
会更好,但是在旧证明中是否可以使用BinNat
代替nat
而无需进行太多修改? (尤其是,用+
更有效的定义替换BinNat
的低效率用法?)
答案 0 :(得分:3)
为了清楚起见,我认为Heap
必须是这样的
这样:
Inductive Heap A : Type :=
| Node : Heap A -> A -> Heap A -> Heap A
| Leaf : Heap A.
将f
定义为
Fixpoint f A (h : Heap A) : list A :=
match h with
| Node h1 a h2 => f h1 ++ a :: f h2
| Leaf => []
end.
如果是这种情况,那么f
不定义之间的同构
所有Heap A
的{{1}}和list A
。相反,我们可以找到一个功能
A
这样
g : forall A, list A -> Heap A
尽管如此,我们想说forall A (l : list A), f (g l) = l
和Heap
都是。{
当它们用于实现相同的某种意义上
抽象,即某种类型的元素集。
我们可以通过一种精确而正式的方式验证这一想法 在具有parametric polymorphism的语言中,例如Coq。这个 原则,称为parametricity,粗略地说 参数多态函数尊重我们强加的关系 在类型上我们用。实例化它们。
这有点抽象,所以让我们试着做更多
具体。假设你有一个列表功能(比如list
)
仅使用foo
和++
。能够用{替换nth
使用参数化的foo
上的等效版本,我们需要做
Heap
的定义是多态的,抽象了函数
列表:
foo
首先通过实例化来证明foo的属性 列表:
Definition foo (T : Set -> Set)
(app : forall A, T A -> T A -> T A)
(nth : forall A, T A -> nat -> option A)
A (l : T A) : T A :=
(* ... *)
现在,因为我们现在Definition list_foo := foo list @app @nth.
Lemma list_foo_lemma : (* Some statement *).
和H_app
与他们相容
列出对应物,因为H_nth
是多态的,理论是
参数化说我们可以证明
foo
有了这个引理,应该可以运输属性
Definition H_foo := foo Heap @H_app @H_nth.
Lemma foo_param : forall A (h : Heap A),
f (H_foo h) = list_foo (f h).
的{{1}}类似属性。list_foo
。例如,作为一个
举个简单的例子,我们可以证明H_foo
是关联的,最多可以
转换为列表:
H_app
参数化的好处在于它适用于任何
参数化多态函数:只要合适
兼容性条件保持您的类型,应该是可能的
以类似的方式关联给定函数的两个实例
forall A (h1 h2 h3 : Heap A),
list_foo (H_app h1 (H_app h2 h3)) =
list_foo (H_app (H_app h1 h2) h3).
。
然而,有两个问题。第一个是必须改变
你的基本定义是多态的,这可能不是这样
坏。然而,更糟糕的是,尽管参数确保了
总是有可能证明foo_param
之下的引理
在某些条件下,Coq不会免费提供给您,而您仍然可以
需要手工显示这些引理。有两件事可以帮助我们
减轻你的痛苦:
Coq(CoqParam)的parametricity plugin应该是。{ 帮助自动为您提供样板证明。我有 但是从来没有使用它,所以我真的不能说它有多容易使用。
Coq Effective Algebra Library(简称CoqEAL)使用
参数化来证明有效算法的事情
推理更方便的。特别是,他们定义
允许在foo_param
和nat
之间切换的优化,如
你建议。在内部,他们使用基于的基础设施
类型推断,你可以适应你的原始
例如,但我听说他们正在迁移他们的
实现使用CoqParam代替。