Coq 程序不动点:递归调用'let'和义务假设

Coq 程序不动点:递归调用'let'和义务假设,coq,totality,Coq,Totality,假设我有以下程序固定点: 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. (为了有一个简单的示例,这个示例基本上以一种非

假设我有以下
程序固定点

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
时,
长度(tl)
确实小于
长度l

但是,当我想解决这个义务的时候

Next Obligation.
我没有我需要的假设

(不知何故,我的印象是,它被理解为“在
let in
位置计算
f(tll)
”,而不是“在实际使用之前延迟计算”)


为了说明区别,如果我“内联”了
让。。。在
语句中:

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.
在这里,我看到了环境中的一些n=hd\u错误[]


我的问题如下: 是否可能有我需要的假设,即让
生成的假设匹配。。。是否使用
语句


注意:移动
let
是一个解决方案,但我很想知道不这样做是否可行。例如,在各种上下文中使用
f_rec
的情况下,它可能很有用,以避免重复
f(tll)

一个技巧是明确要求您需要的假设(我最近在中看到它):


哇,这个小费真不错!
let f_rec := fun pf : length (tl l) < length l => f (tl l) in
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.