I want last k elements of vector. I wrote this code with reference to Coq.Vectors.VectorDef.
Require Import Coq.Reals.Reals.
(* vector of R *)
Inductive Euc:nat -> Type:=
|RO : Euc 0
|Rn : forall {n:nat}, R -> Euc n -> Euc (S n).
Notation "[ ]" := RO.
Notation "[ r1 , .. , r2 ]" := (Rn r1 .. ( Rn r2 RO ) .. ).
Infix ":::" := Rn (at level 60, right associativity).
(* return length of vector *)
Definition EucLength {n}(e:Euc n) :nat:= n.
Definition rectEuc (P:forall {n}, Euc (S n) -> Type)
(bas: forall a:R, P [a])
(rect: forall {n} a (v: Euc (S n)), P v -> P (a ::: v)) :=
fix rectEuc_fix {n} (v: Euc (S n)) : P v :=
match v with
|@Rn 0 a v' =>
match v' with
|RO => bas a
|_ => fun devil => False_ind (@IDProp) devil
end
|@Rn (S nn') a v' => rect a v' (rectEuc_fix v')
|_ => fun devil => False_ind (@IDProp) devil
end.
(* eliminate last element from vector *)
Definition EucElimLast := @rectEuc (fun n _ => Euc n) (fun a => []) (fun _ a _ H => a ::: H).
(* this function has an error *)
Definition rectEucLastN (P:forall {n}, nat -> Euc n -> Type)
(bas: forall {n} k (e:Euc n), P k e)
(rect: forall {n} k a (e:Euc (S n)), P k e -> P (S k) (a ::: e)) :=
fix rectEuc_fix {n} (k:nat) (e:Euc n): P k e :=
match k,e with
|S k', e' ::: es => rect k' e' (rectEuc_fix k' (EucElimLast ((EucLength e)-1) e))
|0%nat, e' ::: es => bas k e
|_, _ => fun devil => False_ind (@IDProp) devil
end.
rectEucLastN
says The type of this term is a product while it is expected to be (P ?n@{n1:=0%nat} ?n0@{k1:=0%nat} ?e@{n1:=0%nat; e1:=[]}).
The problem is the second line from the bottom of the code.
Why does last pattern have an error?
The function term that you see on the branch of
rectEuc
is how you tell Coq that a pattern-match branch is contradictory. In your first recursive function, for instance, you use it to say that the firstv'
cannot be a cons because its length is zero. The reason you are getting the error in the last branch is because that case is not contradictory: nothing in the type of your function prevents the casek = 0
andn = 0
.To write dependently typed programs over indexed families, you often need to use the convoy pattern: to refine the type of an argument
x
after branching on some expression, yourmatch
needs to return a function that abstracts overx
. For instance, this function computes the last element of a vector by recursion over its length. In theS
branch, we need to know that the length ofv
is connected ton
somehow.Here is the code for extracting the last
k
elements. Note that its type uses theNat.min
function to specify the length of the result: the result cannot be larger than the original vector!Personally, I would advise you against programming in this style in Coq, since it makes it difficult to write programs and understand them later. It is usually better to write a program without dependent types and prove after the fact that it has some property that you care about. (E.g. try to show that reversing a list twice yields the same list using vectors!) Of course, there are cases where dependent types are useful, but most of the time they are not needed.