Coq 向量错误:该术语的类型为乘积

Coq 向量错误:该术语的类型为乘积,coq,dependent-type,convoy-pattern,Coq,Dependent Type,Convoy Pattern,我要向量的最后k个元素。我写这段代码时参考了 rectEucLastN说这个术语的类型是一个产品,而它预期是(p?n{n1:=0%nat}?n0{k1:=0%nat}?e{n1:=0%nat;e1:=[])。 问题是代码底部的第二行 为什么最后一个模式有错误?在rectEuc的分支上看到的函数项是如何告诉Coq模式匹配分支是矛盾的。例如,在第一个递归函数中,您使用它来表示第一个v'不能是cons,因为它的长度为零。在最后一个分支中出现错误的原因是,这种情况并不矛盾:函数类型中没有任何内容阻止这种

我要向量的最后k个元素。我写这段代码时参考了

rectEucLastN
这个术语的类型是一个产品,而它预期是(p?n{n1:=0%nat}?n0{k1:=0%nat}?e{n1:=0%nat;e1:=[])。

问题是代码底部的第二行


为什么最后一个模式有错误?

rectEuc
的分支上看到的函数项是如何告诉Coq模式匹配分支是矛盾的。例如,在第一个递归函数中,您使用它来表示第一个
v'
不能是cons,因为它的长度为零。在最后一个分支中出现错误的原因是,这种情况并不矛盾:函数类型中没有任何内容阻止这种情况
k=0
n=0

要在索引族上编写依赖类型的程序,通常需要使用护送模式:要在对某个表达式进行分支后细化参数
x
的类型,您的
match
需要返回一个对
x
进行抽象的函数。例如,此函数通过递归计算向量长度上的最后一个元素。在
S
分支中,我们需要知道
v
的长度以某种方式连接到
n

Definition head n (v : Euc (S n)) : R :=
  match v with
  | x ::: _ => x
  end.

Definition tail n (v : Euc (S n)) : Euc n :=
  match v with
  | _ ::: v => v
  end.

Fixpoint last n : Euc (S n) -> R :=
  match n with
  | 0   => fun v => head 0 v
  | S n => fun v => last n (tail _ v)
  end.
下面是提取最后
k
元素的代码。注意,它的类型使用
Nat.min
函数指定结果的长度:结果不能大于原始向量

Fixpoint but_last n : Euc (S n) -> Euc n :=
  match n with
  | 0   => fun _ => []
  | S n => fun v => head _ v ::: but_last n (tail _ v)
  end.

Fixpoint snoc n (v : Euc n) (x : R) : Euc (S n) :=
  match v with
  | [] => [x]
  | y ::: v => y ::: snoc _ v x
  end.

Fixpoint lastk k : forall n, Euc n -> Euc (Nat.min k n) :=
  match k with
  | 0 => fun _ _ => []
  | S k => fun n =>
    match n return Euc n -> Euc (Nat.min (S k) n) with
    | 0 => fun _ => []
    | S n => fun v =>
      snoc _ (lastk k _ (but_last _ v)) (last _ v)
    end
  end.

就个人而言,我建议您不要在Coq中使用这种风格的编程,因为这样会使编写程序和以后理解它们变得困难。通常最好编写一个没有依赖类型的程序,并在它具有您所关心的某些属性之后进行证明。(例如,尝试证明两次反转列表会产生使用向量的相同列表!)当然,在某些情况下依赖类型是有用的,但大多数情况下不需要依赖类型。

是否可以禁止在
lastk
中使用k>n的参数?我只想要类型为
Euc k
的输出。
Fixpoint but_last n : Euc (S n) -> Euc n :=
  match n with
  | 0   => fun _ => []
  | S n => fun v => head _ v ::: but_last n (tail _ v)
  end.

Fixpoint snoc n (v : Euc n) (x : R) : Euc (S n) :=
  match v with
  | [] => [x]
  | y ::: v => y ::: snoc _ v x
  end.

Fixpoint lastk k : forall n, Euc n -> Euc (Nat.min k n) :=
  match k with
  | 0 => fun _ _ => []
  | S k => fun n =>
    match n return Euc n -> Euc (Nat.min (S k) n) with
    | 0 => fun _ => []
    | S n => fun v =>
      snoc _ (lastk k _ (but_last _ v)) (last _ v)
    end
  end.