Coq添加新变量而不是使用正确的变量

时间:2016-09-12 23:01:32

标签: coq

我正在研究Coq中我自己的向量实现,而且我遇到了一个奇怪的问题。

到目前为止,这是我的代码:

Inductive Fin : nat -> Type :=
  |FZ : forall n, Fin (S n)
  |FS : forall n, Fin n -> Fin (S n).

Definition emptyf(A : Type) : Fin 0 -> A.
  intro e; inversion e.
Defined.

Inductive Vec(A : Type) : nat -> Type :=
  |Nil  : Vec A 0
  |Cons : forall n, A -> Vec A n -> Vec A (S n).

Definition head(A : Type)(n : nat)(v : Vec A (S n)) : A :=
  match v with
  |Cons a _ => a
  end.

Definition tail(A : Type)(n : nat)(v : Vec A (S n)) : Vec A n :=
  match v with
  |Cons _ w => w
  end.

Fixpoint index(A : Type)(n : nat) : Vec A n -> Fin n -> A :=
  match n as n return Vec A n -> Fin n -> A with
  |0   => fun _ i => emptyf _ i
  |S m => fun v i => match i with
                     |FZ _ => head v
                     |FS j => index (tail v) j
                     end
  end.

最高tail的所有内容编译都很好,但是当我尝试编译index时,我收到以下错误:

Error:
In environment
index : forall (A : Type) (n : nat), Vec A n -> Fin n -> A
A : Type
n : nat
m : nat
v : Vec A (S m)
i : Fin (S m)
n0 : nat
j : Fin n0
The term "j" has type "Fin n0" while it is expected to have type "Fin m".

显然,罪魁祸首是Coq引入新变量n0而不是j类型Fin m,即使这是j唯一可能的类型会导致从i构建j。知道为什么会这样,以及我如何能够解决这个问题?

4 个答案:

答案 0 :(得分:3)

请注意,您不需要针对n进行模式匹配,而只需针对Fin n类型的参数进行模式匹配。结果定义更简单。

Fixpoint index {A:Type} {n:nat} (i:Fin n) : Vec A n -> A :=
  match i in Fin n0 return Vec A n0 -> A with
  | FZ => fun v => head v
  | FS j => fun v => index j (tail v)
  end.

Coq实际上足以猜测注释。

Fixpoint index {A:Type} {n:nat} (i:Fin n) : Vec A n -> A :=
  match i with
  | FZ => fun v => head v
  | FS j => fun v => index j (tail v)
  end.

答案 1 :(得分:2)

我发现VecFin一般很难使用,所以我这些天使用math-comp中的'I_nn.-tuples T,这些只是自然而已附有无关证据的清单。但是,如果您想继续复杂模式匹配的乐趣,您可以尝试定义更强大的模式匹配原则:

Definition fin_case T m (i : Fin m) : T -> (Fin (pred m) -> T) -> T :=
  match i with
  | FZ _   => fun fn fz => fn
  | FS _ j => fun fn fz => fz j
  end.

一旦你有fin_case,你的函数定义就可以了:

Fixpoint index (A : Type) (n : nat) : Vec A n -> Fin n -> A :=
  match n as n return Vec A n -> Fin n -> A with
  | 0   => fun _ i => emptyf _ i
  | S m => fun v i => fin_case i (head v) (index (tail v))
  end.

答案 2 :(得分:2)

使用 match i in Fin (S n0) return n0 = m -> A with ... => fun H : n0 = m => ... end eq_refl 时,您可能会丢失信息。我使用convoy pattern将信息返回到上下文中。

n0 = m

使Coq能够将信息(match H with ... end)放入上下文中。它作为函数参数发送到match子句中。要在类型检查中使用它,我使用Fin n0 = Fin m,以便Coq理解Fixpoint index(A : Type)(n : nat) : Vec A n -> Fin n -> A := match n as n return Vec A n -> Fin n -> A with |0 => fun _ i => emptyf _ i |S m => fun v i => match i in Fin (S n') return n' = m -> A with |FZ _ => fun _ => head _ _ v |FS _ j => fun H => index (tail v) (match H with eq_refl _ => j end) end eq_refl end. 。 这是解决方案。

refine

当类型检查不能理解两件事情是相同的时,通常护航模式可以帮助您将信息传递到上下文中。我还建议使用public function connect(UserInterface $user, UserResponseInterface $response)逐步建立术语。它让您可以看到上下文中的信息。

答案 3 :(得分:2)

只是为了添加其他答案,基于策略的解决方案:

Fixpoint index (A : Type) (n : nat) (v : Vec A n) (i : Fin n) : A.
  destruct v as [| n h tl].
  - exact (emptyf A i).
  - inversion i as [ | ? i'].
    + exact h.
    + exact (index _ _ tl i').
Defined.

inversion策略处理"信息丢失"。如果您尝试Print index.,结果不会很漂亮,但Coq基本上使用了@larsr提到的护航模式。

请注意,此方法不会在n上使用模式匹配。它改为对矢量参数进行模式匹配,这就是为什么它不需要headtail函数。