我目前正在与Coq合作,我遇到了一个我不知道如何解决的问题。
我们说我们正在使用给定的类型,我会以nat
为例,我想使用可能失败的函数f
。为了弥补失败,我们将f
定义为nat -> option nat
类型。
现在我有一个假设H: nat -> bool
,其中f不会失败,我甚至证明了引理
Lemma no_error_in_f : forall (n:nat), H n = true -> exists (u:nat), f n = Some u.
我想定义一个函数g: nat->nat
,如果f
满足,则n
的结果为H n
,否则只给n
。这个功能应该很好定义,但我不知道如何正确定义它。
如果我尝试一些幼稚的东西
Definition g (n:nat) := if H n then f n else n.
,打字系统出现问题。
有谁知道如何收集所有元素并告诉系统该定义是合法的?
答案 0 :(得分:1)
我在这里给出的解决方案与问题中给出的假设相同。
Axiom f : nat -> option nat.
Axiom H : nat -> bool.
Axiom no_error_in_f : forall n,
H n = true -> exists u, f n = Some u.
Lemma no_error_in_f_bis : forall n,
H n = true -> f n <> None.
Proof.
intros. apply no_error_in_f in H0. destruct H0. rewrite H0. discriminate.
Qed.
Definition g n :=
match H n as b return H n = b -> _ with
| true => fun H =>
match f n as f0 return f n = f0 -> _ with
| Some n0 => fun _ => n0
| None => fun H0 => match no_error_in_f_bis n H H0 with end
end eq_refl
| false => fun _ => n
end eq_refl.
我使用另一个引理而不是no_error_in_f
,这更便于证明False
。
请注意,此函数的两个概念(使用return
的{{1}}构造,破坏match
的证明以显示分支无法访问)在此处解释:{{3} }。
答案 1 :(得分:0)
您的开发中存在两个问题。一个是你不能使用no_error_in_f
来定义Coq中的g
而不假设其他公理,因为Coq不允许从证明中提取计算信息(检查here以获取更多细节)。另一个问题是,您无法在H
表达式中使用if
,因为它会返回Prop
而不是bool
(请检查this answer更多细节)。
答案 2 :(得分:0)
我找到了一种方法,如果有人有兴趣,这是我的解决方案:
Definition g (n:nat) :nat :=
(match (H n) as a return a = H n -> nat with
| true =>
(fun H_true => (match (f n) as b return b = f n -> nat with
| Some u => (fun _ => u)
| None => (fun H1 => False_rec _ (no_error_in_f H_true H1))
end) (eq_refl f n))
| false => n
end) (eq_refl H n).
对于那些想知道它意味着什么的人,False_rec将第二个参数作为False的证明,并证明匹配是不可能的。
一词 (match (f n) as b return b = f n -> nat with
| Some u => (fun _ => u)
| None => (fun H1 => False_rec _ (no_error_in_f H_true H1))
end) (eq_refl f n))
类型为f n = f n-> nat
,当我将其应用于证明eq_refl (f n)
时(证明f n = f n,因此键入f n = f n
),我得到nat
。
这个技巧允许我获得H1
,这是f n = None
使用相等的反射和模式匹配获得的证明,并且我将在{{1}的证明中使用}。
另一场比赛也是如此。