如何让Coq接受以下Fixpoint?

时间:2017-12-23 10:25:49

标签: coq

我正在尝试为lambda演算编写替换函数,并且在递归调用e上的替换之前,在lambda抽象(\ x.e)的情况下,我必须重命名e中的变量。我怎样才能在Coq中表示这种逻辑?

以下是一个最基本的例子,Coq给出的错误是无法猜测减少的参数。在简化的替换中,为什么Coq不能得到相同的电感尺寸?

Fixpoint replace (x: nat) (y: nat) (e: exp): exp := e.

Fixpoint substitute (x: nat) (t: exp) (body: exp): exp :=
match body with
| Abs xp e => Abs 0 (substitute x t (replace x 0 e))
| _ => Unit
end.

实际替换看起来像这样

Fixpoint replace (x: nat) (y: nat) (e: exp): exp :=
match e with
| Val => Val
| Var xp => if beq_nat x xp then Var y else e
| Ref f => Ref (replace x y f)
| Abs xp bd => Abs xp (replace x y bd)
| App e1 e2 => App (replace x y e1) (replace x y e2)
| Deref f => Deref (replace x y f)
| Loc l => Loc l
| Assign e1 e2 => Assign (replace x y e1) (replace x y e2)
| Unit => Unit
end.

1 个答案:

答案 0 :(得分:4)

通常,Coq不接受f(x) = f(g(subterm of x))形式的递归Fixpoints。当然,这是有道理的,因为g可能是一个增加术语大小的函数。

通常,解决方案是找到终止度量,而不是Fixpoint使用的普通“是子项”。在这里,您可以定义一个函数height : exp -> nat,对于叶节点为0,否则为max子树。然后,Coq有几种基于这种措施定义终止功能的方法,例如, Program FixpointFunction,或者您甚至可以手动定义一个Fixpoint,它接受一个表示高度限制的附加参数(如果该参数变为0,则返回一个虚拟值)。程序Fixpoint将为您提供证明义务,即每次递归调用都会减少该度量,并证明您需要证明replace保留高度的引理。

在替换的特定情况下,您可以尝试的另一个技巧是定义一个函数来应用多替换(从变量映射到表达式),而不是替换单个变量的函数。这样,在Abs-case中,您可以将重命名添加到要应用的替换而不是直接执行,然后该函数在结构上是递归的。