如何证明size_prgm
的终止?我试过了,但是无法想出一个完善的关系来传递给Fix
。
Inductive Stmt : Set :=
| assign: Stmt
| if': (list Stmt) -> (list Stmt) -> Stmt.
Fixpoint size_prgm (p: list Stmt) : nat :=
match p with
| nil => 0
| s::t => size_prgm t +
match s with
| assign => 1
| if' b0 b1 => S (size_prgm b0 + size_prgm b1)
end
end.
答案 0 :(得分:3)
终止oracle比过去好多了。使用sum_with
定义函数fold_left
并将其递归到size_prgm
的递归调用非常有效。
Require Import List.
Inductive Stmt : Set :=
| assign: Stmt
| if': (list Stmt) -> (list Stmt) -> Stmt.
Definition sum_with {A : Type} (f : A -> nat) (xs : list A) : nat :=
fold_left (fun n a => n + f a) xs 0.
Fixpoint size_prgm (p: Stmt) : nat :=
match p with
| assign => 1
| if' b0 b1 => sum_with size_prgm b1 + sum_with size_prgm b0
end.
答案 1 :(得分:1)
简短回答,因为我现在没有太多时间(我会稍后再回复你): 这是一个非常普通(而且很愚蠢)的问题,每个Coq用户都必须经历一天。
如果我没记错的话,这个问题有两个“通用”解决方案,还有很多非常具体的解决方案。对于前两位:
使用相互递归类型:代码的问题在于您在list Stmt
类型中使用Stmt
,而Coq无法计算您想到的归纳原则。但你可以使用像
Inductive Stmt : Set :=
| assign : Stmt
| if': list_Stmt -> list_Stmt -> Stmt
with list_Stmt : Set :=
| Nil_Stmt : list_Stmt
| Cons_Stmt : Stmt -> list_Stmt -> list_Stmt.
现在使用此类型编写您的函数,并在此类型与原始Stmt
类型之间进行双射。
您可以尝试浏览Coq-Club邮件列表,这类主题是反复出现的。
希望它有点帮助, V