我试图在Coq上定义一个相对简单的函数:
(* Preliminaries *)
Require Import Vector.
Definition Vnth {A:Type} {n} (v : Vector.t A n) : forall i, i < n -> A. admit. Defined.
(* Problematic definition below *)
Definition VnthIndexMapped {A:Type}
{i o:nat}
(x: Vector.t (option A) i)
(f': nat -> option nat)
(f'_spec: forall x, x<o ->
(forall z,(((f' x) = Some z) -> z < i)) \/
(f' x = None))
(n:nat) (np: n<o)
: option A
:=
match (f' n) as fn, (f'_spec n np) return f' n = fn -> option A with
| None, _ => fun _ => None
| Some z, or_introl zc1 => fun p => Vnth x z (zc1 z p)
| Some z, or_intror _ => fun _ => None (* impossible case *)
end.
收到以下错误:
Error:
Incorrect elimination of "f'_spec n np" in the inductive type "or":
the return type has sort "Type" while it should be "Prop".
Elimination of an inductive object of sort Prop
is not allowed on a predicate in sort Type
because proofs can be eliminated only to build proofs.
我想我理解这种限制的原因,但我很难找到解决方法。如何实现这样的事情?基本上我有一个函数f'
我有一个单独的证明,值小于'o'它返回None
或(Some z)
z
小于{{} 1}}我想在我的定义中使用它。
答案 0 :(得分:2)
有两种方法可以解决这样的问题:简单方法和困难方式。
简单的方法是思考你是否做了比你更复杂的事情。在这种情况下,如果仔细查看,您会发现f'_spec
等同于以下语句,这样可以避免\/
:
Lemma f'_spec_equiv i o (f': nat -> option nat) :
(forall x, x<o ->
(forall z,(((f' x) = Some z) -> z < i)) \/
(f' x = None))
<-> (forall x, x<o -> forall z,(((f' x) = Some z) -> z < i)).
Proof.
split.
- intros f'_spec x Hx z Hf.
destruct (f'_spec _ Hx); eauto; congruence.
- intros f'_spec x Hx.
left. eauto.
Qed.
因此,您可以在f'_spec
中重新定义VnthIndexedMapped
的类型并直接使用该证明。
当然,有时候没有办法简化事情。然后你需要严格遵循,并尝试理解Coq的细节,使其接受你想要的东西。
正如Vinz所指出的,你通常(有例外)不能消除命题构造计算的证据。但是,您可以取消构建另一个证明的证明,也许该证明可以满足您的需要。例如,你可以这样写:
Definition VnthIndexMapped {A:Type}
{i o:nat}
(x: Vector.t (option A) i)
(f': nat -> option nat)
(f'_spec: forall x, x<o ->
(forall z,(((f' x) = Some z) -> z < i)) \/
(f' x = None))
(n:nat) (np: n<o)
: option A
:=
match (f' n) as fn return f' n = fn -> option A with
| None => fun _ => None
| Some z => fun p =>
let p' := proj1 (f'_spec_equiv i o f') f'_spec n np z p in
Vnth x z p'
end eq_refl.
这个定义使用了f'_spec
的两个公式都是等价的证明,但是如果它们不相同,那么同样的想法也适用,并且你有一些允许你从一个到另一个的引理。< / p>
我个人并不喜欢这种风格,因为它很难使用,并且适合那些阅读复杂的程序。但它可以有它的用途......
答案 1 :(得分:0)
问题是您希望通过检查f'_spec
的内容来构建术语。这种分离存在于Prop
中,因此它只能构建其他Prop
。您希望在Type
中构建更多内容。因此,您需要至少在Set
(更常见地在Type
中)的析取版本。我建议您将Foo \/ Bar
语句替换为使用sumbool
的{{1}},并使用符号{Foo}+{Bar}
。