I don't understand your approach. You're always returning a non-empty vector when the argument is a non-empty vector, but take
must return nil
when p=0
regardless of the vector.
Here's one approach to building take
. Rather than using the hypothesis p <= n
, I express the length of the argument n
as a sum of the number p
of elements to take and the number of trailing elements m
, which is possible iff p <= n
. This allows for an easier recursive definition, because (S p') + m
is structurally equal to S (p' + m)
. Note that the discrimination is on the number of elements to take: return nil
if taking 0, return cons head new_tail
otherwise.
This version of the take
function has the desired computational behavior, so all that's left is to define one with the desired proof content. I use the Program
feature to do this conveniently: fill in the computational content (trivial, I just need to say that I want to use m = n - p
), then complete the proof obligations (which are simple arithmetic).
Require Import Arith.
Require Import Vector.
Fixpoint take_plus {A} {m} (p:nat) : t A (p+m) -> t A p :=
match p return t A (p+m) -> t A p with
| 0 => fun a => nil _
| S p' => fun a => cons A (hd a) _ (take_plus p' (tl a))
end.
Program Definition take A n p (a : t A n) (H : p <= n) : t A p :=
take_plus (m := n - p) p a.
Solve Obligations using auto with arith.
For your newdrop : forall A n p, t A n -> p <= n -> t A (n-p)
, the following approach works. You need to help Coq by telling it what p
and n
become in the recursive call.
Program Fixpoint newdrop {A} {n} p : t A n -> p <= n -> t A (n-p) :=
match p return t A n -> p <= n -> t A (n-p) with
| 0 => fun a H => a
| S p' => fun a H => newdrop p' (tl a) (_ : p' <= n - 1)
end.
Next Obligation.
omega.
Qed.
Next Obligation.
omega.
Qed.
Next Obligation.
omega.
Qed.
Next Obligation.
omega.
Qed.
I don't know why Solve Obligations using omega.
doesn't work but solving each obligation individually works.