在处理非依赖类型时,Coq(通常)推断出哪个参数在固定点中减少。但是,依赖类型不是这种情况。
例如,考虑下面的示例,其中我有一个类型A_list
,该类型确保属性P保留列表中所有元素(类型A):
Require Import Coq.Lists.List.
Variable A: Type.
Variable P: A -> Prop.
Definition A_list := {a: list A | Forall P a}.
现在,说我想让一个固定点递归地使用这样的列表(这里的两个引理并不有趣。dummy_arg是模拟使用多个参数的。):
Lemma Forall_tl: forall P (h: A) t, Forall P (h::t) -> Forall P t.
Admitted.
Lemma aux: forall (l1: list A) l2 P, l1 = l2 -> Forall P l1 -> Forall P l2.
Admitted.
Fixpoint my_fixpoint (l: A_list) (dummy_arg: A) :=
match (proj1_sig l) as x return proj1_sig l = x -> bool with
| nil => fun _ => true
| hd::tl =>
fun h =>
my_fixpoint (exist (Forall P) tl (Forall_tl P hd tl (aux _ _ _ h (proj2_sig l)))) dummy_arg
end eq_refl.
这与预期的一样,返回错误“无法猜测Fix的递减参数”。因为严格来说,因为我们并没有减少争论。尽管如此,我们显然在proj1_sig l
(嵌入在sig
中的列表上)减少了。
使用Program Fixpoint
可能可以解决此问题,但是由于在依赖类型的投影上减小它必须是一种非常常见的模式,因此我想知道管理这种情况的“正确”方法是什么。
答案 0 :(得分:2)
您可以使用我在this answer中提到的一种方法(包括Program
)解决此问题。
如果将列表和证明脱钩,则可以使用普通递归来完成:
Fixpoint my_fixpoint (l: list A) (pf : Forall P l) (dummy_arg: A) : bool :=
match l as x return Forall P x -> bool with
| nil => fun _ => true
| hd::tl => fun h => my_fixpoint tl (Forall_tl P hd tl h) dummy_arg
end pf.