说我有以下Program Fixpoint
:
From Coq Require Import List Program.
Import ListNotations.
Program Fixpoint f l {measure (length l)}: list nat :=
let f_rec := (f (tl l) ) in
match hd_error l with
| Some n => n :: f_rec
| None => []
end.
(这个例子基本上以非常愚蠢的方式返回l
,为了有一个简单的例子。)
在这里,我对f
进行了递归调用(存储在f_rec
中),仅在l
包含元素时使用,这可确保在我使用f_rec
时,length (tl l)
确实小于length l
。
然而,当我想解决义务时
Next Obligation.
我没有我需要的假设hd_error l = Some n
。
(不知何故,我的印象是它被理解为“f (tl l)
地方的计算let in
”,而不是“在实际使用之前延迟计算”。)
为了说明差异,如果我“内联”let ... in
语句:
Program Fixpoint f l {measure (length l)}: list nat :=
match hd_error l with
| Some n => n :: (f (tl l) )
| None => []
end.
Next Obligation.
destruct l.
这里我在环境中有Heq_anonymous : Some n = hd_error []
。
我的问题如下:
是否有可能得到我需要的假设,即假设是由match ... with
陈述产生的?
N.B。:移动let
是一个解决方案,但我很想知道这是否可行而不这样做。例如,在f_rec
用于各种上下文的情况下,它可能很有用,以避免重复f (tl l)
。
答案 0 :(得分:2)
一个技巧是明确要求你需要的假设(我最近在this answer Joachim Breitner中看到了这个假设:
let f_rec := fun pf : length (tl l) < length l => f (tl l) in
这样,只有在有意义的情况下才能使用f_rec
。
Program Fixpoint f l {measure (length l)}: list nat :=
let f_rec := fun pf : length (tl l) < length l => f (tl l) in
match hd_error l with
| Some n => n :: f_rec _
| None => []
end.
Next Obligation. destruct l; [discriminate | auto]. Qed.