如何使Coq接受以下固定点?

如何使Coq接受以下固定点?,coq,Coq,我试图为lambda演算编写一个替换函数,如果lambda抽象(\x.e),在递归调用e上的替换之前,我必须重命名e中的变量。我如何在Coq中表示这种逻辑 下面是一个简单的例子,Coq给出了一个错误,即它无法猜测递减参数。在简化的替换中,为什么Coq不能得到相同电感尺寸的e Fixpoint replace (x: nat) (y: nat) (e: exp): exp := e. Fixpoint substitute (x: nat) (t: exp) (body: exp): exp :

我试图为lambda演算编写一个替换函数,如果lambda抽象(\x.e),在递归调用e上的替换之前,我必须重命名e中的变量。我如何在Coq中表示这种逻辑

下面是一个简单的例子,Coq给出了一个错误,即它无法猜测递减参数。在简化的替换中,为什么Coq不能得到相同电感尺寸的e

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.

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

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


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

fixpointreplace(x:nat)(y:nat)(e:exp){struct e}:exp:=e.
definitionreplace(x:nat)(y:nat)(e:exp):exp:=e
适用于简化的情况。@AntonTrunov我如何使下面的
replace
实现工作?我不确定总体检查器是否允许您使用这种实现。也许《软件基础》第二卷可以提供帮助。