尝试在异构向量上定义类似 "rect2" 的函数
Trying to define a "rect2"-like function on heterogeneous vectors
我有以下(希望没有争议!)异构向量的定义:
Require Vectors.Vector.
Import Vector.VectorNotations.
Section hvec.
Variable A : Type.
Variable B : A -> Type.
Inductive t : forall k : nat, Vector.t A k -> Type :=
| nil : t 0 []
| cons :
forall (a : A) (b : B a) (k : nat) (v : Vector.t A k), t k v -> t (S k) (a :: v).
Local Notation "[! ]" := nil (format "[! ]").
Local Notation "h :! t" := (cons _ h _ _ t) (at level 60, right associativity).
Local Notation "[! x ]" := (x :! [! ]).
我想定义一个 eqb
函数(假设有一个用于组件类型的函数)。要定义一个,我想我需要像 rect2
这样的东西。从Vectors库类推,我觉得它的类型应该是这样的:
Fixpoint rect2
(P : forall {k : nat} {v : Vector.t A k} (hv0 hv1 : t k v), Type)
(bas : P nil nil)
(rect : forall {k : nat} {v : Vector.t A k} {hv0 hv1 : t k v},
P hv0 hv1 ->
forall (a : A) (b0 b1 : B a), P (b0 :! hv0) (b1 :! hv1))
{k : nat}
: forall (v : Vector.t A k) (hv0 hv1 : t k v), P hv0 hv1.
问题是我不知道如何让所有依赖类型正确通过。匹配 k
,然后 v
然后 hv0
(这对我来说似乎是显而易见的方法)似乎不起作用。问题是你走到这一步了:
refine (
match k with
| 0 =>
fun v =>
match v with
| [] =>
fun hv0 hv1 => _
| _ => tt
end
| S k' => _
end
).
但无法在 hv0
上合理匹配。没有 return 注释 (match hv0 with ...
),类型如下所示:
...
v : Vector.t A 0
hv0, hv1 : t 0 []
============================
P 0 [] hv0 hv1
(注意义务中的 hv0
,而不是 nil
)。尝试编写 match hv0 as hv0' return P 0 [] hv0' hv1 with ...
之类的 return 注释没有帮助,因为现在 hv0'
的类型已经丢失了 k
为零的事实。
我假设有一个聪明的技巧/正确的顺序来写这种东西。有人可以帮忙吗?
您可以使用相关的相关模式匹配进行反转,如下所示:
Fixpoint rect2
(P : forall {k : nat} {v : Vector.t A k} (hv0 hv1 : t k v), Type)
(bas : P nil nil)
(rect : forall {k : nat} {v : Vector.t A k} {hv0 hv1 : t k v},
P hv0 hv1 ->
forall (a : A) (b0 b1 : B a), P (b0 :! hv0) (b1 :! hv1))
{k : nat}
: forall (v : Vector.t A k) (hv0 hv1 : t k v), P hv0 hv1.
Proof.
intro v.
induction v using Vector.t_rect.
- intros hv0.
refine (
(* match on hv0, retaining info on its indices *)
match hv0 as z in t k l return forall (hv1 : t k l),
(* match on the abstracted index l : Vector.t A k *)
match l as l' in Vector.t _ k'
return forall (hv0 hv1 : t k' l'), Type
with
(* when l = [] we have our goal *)
| [] => P 0 []
(* otherwise we create a dummy goal that we can fulfill *)
| _ => fun _ _ => unit
end z hv1
with
| [!] => _ (* Actual goal with hv0 replaced by [!] *)
| _ => fun _ => tt (* Dummy goal of type unit *)
end).
尝试一下这些类型的模式匹配可以告诉您依赖类型如何工作(或不工作),但它很快就会变得乏味。更进一步,Equations 库提供了一些实用程序来处理类型依赖,特别是帮助处理这种依赖倒置。
这是使用方程式的完整解决方案:
Require Vectors.Vector.
Import Vector.VectorNotations.
From Equations Require Import Equations.
Module VectorInd.
(* Provided by Equations *)
Derive Signature NoConfusionHom for Vector.t.
End VectorInd.
Import VectorInd.
Section hvec.
Variable A : Type.
Variable B : A -> Type.
Inductive t : forall k : nat, Vector.t A k -> Type :=
| nil : t 0 []
| cons :
forall (a : A) (b : B a) (k : nat) (v : Vector.t A k), t k v -> t (S k) (a :: v).
Local Notation "[! ]" := nil (format "[! ]").
Local Notation "h :! t" := (cons _ h _ _ t) (at level 60, right associativity).
Local Notation "[! x ]" := (x :! [! ]).
(* Provided by Equations *)
Derive Signature NoConfusionHom for t.
Fixpoint rect2
(P : forall {k : nat} {v : Vector.t A k} (hv0 hv1 : t k v), Type)
(bas : P nil nil)
(rect : forall {k : nat} {v : Vector.t A k} {hv0 hv1 : t k v},
P hv0 hv1 ->
forall (a : A) (b0 b1 : B a), P (b0 :! hv0) (b1 :! hv1))
{k : nat}
: forall (v : Vector.t A k) (hv0 hv1 : t k v), P hv0 hv1.
Proof.
intro v.
induction v using Vector.t_rect.
all: intros hv0 hv1; depelim hv0; depelim hv1.
- apply bas.
- now apply rect, IHv.
Defined.
我有以下(希望没有争议!)异构向量的定义:
Require Vectors.Vector.
Import Vector.VectorNotations.
Section hvec.
Variable A : Type.
Variable B : A -> Type.
Inductive t : forall k : nat, Vector.t A k -> Type :=
| nil : t 0 []
| cons :
forall (a : A) (b : B a) (k : nat) (v : Vector.t A k), t k v -> t (S k) (a :: v).
Local Notation "[! ]" := nil (format "[! ]").
Local Notation "h :! t" := (cons _ h _ _ t) (at level 60, right associativity).
Local Notation "[! x ]" := (x :! [! ]).
我想定义一个 eqb
函数(假设有一个用于组件类型的函数)。要定义一个,我想我需要像 rect2
这样的东西。从Vectors库类推,我觉得它的类型应该是这样的:
Fixpoint rect2
(P : forall {k : nat} {v : Vector.t A k} (hv0 hv1 : t k v), Type)
(bas : P nil nil)
(rect : forall {k : nat} {v : Vector.t A k} {hv0 hv1 : t k v},
P hv0 hv1 ->
forall (a : A) (b0 b1 : B a), P (b0 :! hv0) (b1 :! hv1))
{k : nat}
: forall (v : Vector.t A k) (hv0 hv1 : t k v), P hv0 hv1.
问题是我不知道如何让所有依赖类型正确通过。匹配 k
,然后 v
然后 hv0
(这对我来说似乎是显而易见的方法)似乎不起作用。问题是你走到这一步了:
refine (
match k with
| 0 =>
fun v =>
match v with
| [] =>
fun hv0 hv1 => _
| _ => tt
end
| S k' => _
end
).
但无法在 hv0
上合理匹配。没有 return 注释 (match hv0 with ...
),类型如下所示:
...
v : Vector.t A 0
hv0, hv1 : t 0 []
============================
P 0 [] hv0 hv1
(注意义务中的 hv0
,而不是 nil
)。尝试编写 match hv0 as hv0' return P 0 [] hv0' hv1 with ...
之类的 return 注释没有帮助,因为现在 hv0'
的类型已经丢失了 k
为零的事实。
我假设有一个聪明的技巧/正确的顺序来写这种东西。有人可以帮忙吗?
您可以使用相关的相关模式匹配进行反转,如下所示:
Fixpoint rect2
(P : forall {k : nat} {v : Vector.t A k} (hv0 hv1 : t k v), Type)
(bas : P nil nil)
(rect : forall {k : nat} {v : Vector.t A k} {hv0 hv1 : t k v},
P hv0 hv1 ->
forall (a : A) (b0 b1 : B a), P (b0 :! hv0) (b1 :! hv1))
{k : nat}
: forall (v : Vector.t A k) (hv0 hv1 : t k v), P hv0 hv1.
Proof.
intro v.
induction v using Vector.t_rect.
- intros hv0.
refine (
(* match on hv0, retaining info on its indices *)
match hv0 as z in t k l return forall (hv1 : t k l),
(* match on the abstracted index l : Vector.t A k *)
match l as l' in Vector.t _ k'
return forall (hv0 hv1 : t k' l'), Type
with
(* when l = [] we have our goal *)
| [] => P 0 []
(* otherwise we create a dummy goal that we can fulfill *)
| _ => fun _ _ => unit
end z hv1
with
| [!] => _ (* Actual goal with hv0 replaced by [!] *)
| _ => fun _ => tt (* Dummy goal of type unit *)
end).
尝试一下这些类型的模式匹配可以告诉您依赖类型如何工作(或不工作),但它很快就会变得乏味。更进一步,Equations 库提供了一些实用程序来处理类型依赖,特别是帮助处理这种依赖倒置。 这是使用方程式的完整解决方案:
Require Vectors.Vector.
Import Vector.VectorNotations.
From Equations Require Import Equations.
Module VectorInd.
(* Provided by Equations *)
Derive Signature NoConfusionHom for Vector.t.
End VectorInd.
Import VectorInd.
Section hvec.
Variable A : Type.
Variable B : A -> Type.
Inductive t : forall k : nat, Vector.t A k -> Type :=
| nil : t 0 []
| cons :
forall (a : A) (b : B a) (k : nat) (v : Vector.t A k), t k v -> t (S k) (a :: v).
Local Notation "[! ]" := nil (format "[! ]").
Local Notation "h :! t" := (cons _ h _ _ t) (at level 60, right associativity).
Local Notation "[! x ]" := (x :! [! ]).
(* Provided by Equations *)
Derive Signature NoConfusionHom for t.
Fixpoint rect2
(P : forall {k : nat} {v : Vector.t A k} (hv0 hv1 : t k v), Type)
(bas : P nil nil)
(rect : forall {k : nat} {v : Vector.t A k} {hv0 hv1 : t k v},
P hv0 hv1 ->
forall (a : A) (b0 b1 : B a), P (b0 :! hv0) (b1 :! hv1))
{k : nat}
: forall (v : Vector.t A k) (hv0 hv1 : t k v), P hv0 hv1.
Proof.
intro v.
induction v using Vector.t_rect.
all: intros hv0 hv1; depelim hv0; depelim hv1.
- apply bas.
- now apply rect, IHv.
Defined.