模式匹配两个列表,其类型依赖于 Coq 类型
Pattern match with two list whose type is dependent type on Coq
我定义了这个函数。
Inductive Euc:nat -> Type:=
|RO : Euc 0
|Rn : forall {n:nat}, R -> Euc n -> Euc (S n).
Notation "[ ]" := RO.
Infix ":::" := Rn (at level 60, right associativity).
Fixpoint QE {A}(b c:Euc A) :=
match b,c with
|b':::bs, c'::: cs => (b'+c') ::: QE bs cs
|_, _ => []
end.
我遇到错误“术语“[]”的类型为“Euc 0”,而预期的类型为“Euc A”。
我如何教 Coq Euc 0
是 Euc A
?
Coq 不知道唯一剩下的模式是“RO”构造函数,因此您无法 return 一个空的 Euc。
要解决这个问题,只需删除 _ 并专门化案例:
Fixpoint QE {A}(b c:Euc A) : Euc A.
refine (match b,c with
|RO, RO => _
|H => ????
end).
这迫使 coq 了解您正在处理特定的构造函数。
此外,Coq 总是会实例化新变量(不是类型)来消除,因此 coq 可能会抱怨 bs 和 cs 具有不同的索引。
coq vectordef 库有几个如何管理它的例子。
第一种更成熟的方法是使用消除方案,注意你可以使用 head 和 last 破坏一个 non-zero 向量。
例如:
Definition rect_euc {n : nat} (v : Euc (S n)) :
forall (P : Euc (S n) -> Type) (H : forall ys a, P (a ::: ys)), P v.
refine (match v with
|@Rn _ _ _ => _
|R0 => _
end).
apply idProp.
intros; apply H.
Defined.
现在,您只需使用该方案来破坏两个向量,同时保留两个向量的长度:
Fixpoint QE (n : nat) {struct n} : Euc n -> Euc n -> Euc n :=
match n as c return Euc c -> Euc c -> Euc c with
| S m => fun a =>
(@rect_euc _ a _ (fun xs x b =>
(@rect_euc _ b _ (fun ys y => (x + y) ::: @QE m xs ys))))
| 0 => fun xs ys => []
end.
或者,您可以使用 coq 策略来记住两个索引相等:
Fixpoint QE' (n : nat) (b : Euc n) : Euc n -> Euc n.
refine (match b in Euc n return Euc n -> Euc n with
|@Rn m x xs => _
|@RO => fun H => []
end).
remember (S m).
intro H; destruct H as [| k y ys].
inversion Heqn0.
inversion Heqn0.
subst; exact ((x + y) ::: QE' _ xs ys).
Defined.
我定义了这个函数。
Inductive Euc:nat -> Type:=
|RO : Euc 0
|Rn : forall {n:nat}, R -> Euc n -> Euc (S n).
Notation "[ ]" := RO.
Infix ":::" := Rn (at level 60, right associativity).
Fixpoint QE {A}(b c:Euc A) :=
match b,c with
|b':::bs, c'::: cs => (b'+c') ::: QE bs cs
|_, _ => []
end.
我遇到错误“术语“[]”的类型为“Euc 0”,而预期的类型为“Euc A”。
我如何教 Coq Euc 0
是 Euc A
?
Coq 不知道唯一剩下的模式是“RO”构造函数,因此您无法 return 一个空的 Euc。 要解决这个问题,只需删除 _ 并专门化案例:
Fixpoint QE {A}(b c:Euc A) : Euc A.
refine (match b,c with
|RO, RO => _
|H => ????
end).
这迫使 coq 了解您正在处理特定的构造函数。 此外,Coq 总是会实例化新变量(不是类型)来消除,因此 coq 可能会抱怨 bs 和 cs 具有不同的索引。 coq vectordef 库有几个如何管理它的例子。 第一种更成熟的方法是使用消除方案,注意你可以使用 head 和 last 破坏一个 non-zero 向量。 例如:
Definition rect_euc {n : nat} (v : Euc (S n)) :
forall (P : Euc (S n) -> Type) (H : forall ys a, P (a ::: ys)), P v.
refine (match v with
|@Rn _ _ _ => _
|R0 => _
end).
apply idProp.
intros; apply H.
Defined.
现在,您只需使用该方案来破坏两个向量,同时保留两个向量的长度:
Fixpoint QE (n : nat) {struct n} : Euc n -> Euc n -> Euc n :=
match n as c return Euc c -> Euc c -> Euc c with
| S m => fun a =>
(@rect_euc _ a _ (fun xs x b =>
(@rect_euc _ b _ (fun ys y => (x + y) ::: @QE m xs ys))))
| 0 => fun xs ys => []
end.
或者,您可以使用 coq 策略来记住两个索引相等:
Fixpoint QE' (n : nat) (b : Euc n) : Euc n -> Euc n.
refine (match b in Euc n return Euc n -> Euc n with
|@Rn m x xs => _
|@RO => fun H => []
end).
remember (S m).
intro H; destruct H as [| k y ys].
inversion Heqn0.
inversion Heqn0.
subst; exact ((x + y) ::: QE' _ xs ys).
Defined.