Coq "convoy pattern"

853 views Asked by At

I am trying to use "convoy pattern" to preserve dependency between 3 variables (two parameters and return value):

Require Import Vector.

(* "sparse" vector type *)
Notation svector A n := (Vector.t (option A) n).

Fixpoint svector_is_dense {A} {n} (v:svector A n) : Prop :=
  match v with
  | Vector.nil => True
  | Vector.cons (None) _ _ => False
  | Vector.cons (Some _) _ xs => svector_is_dense xs
  end.

Lemma svector_tl_dense {A} {n} {v: svector A (S n)}:
  svector_is_dense v -> svector_is_dense (Vector.tl v).
Admitted.

Lemma svector_hd {A} {n} (v:svector A (S n)): svector_is_dense v -> A.
Admitted.

Fixpoint vector_from_svector {A} {n} {v:svector A n} (D:svector_is_dense v): Vector.t A n :=
  match n return (svector A n) -> (svector_is_dense v) -> (Vector.t A n) with
  | O => fun _ _ => @Vector.nil A
  | (S p) => fun v0 D0 => Vector.cons
                            (svector_hd v0 D0)
                            (vector_from_svector (Vector.tl v) (svector_tl_dense D))
  end v D.

The problem arises in last definition. Any suggestions why it is not working?

1

There are 1 answers

0
Vinz On BEST ANSWER

You got it almost right. The issue is in your return clause, which is non-dependent. What you need is

match n return forall (w: svector A n), (svector_is_dense w) -> (Vector.t A n) with

so that D0 is not of type svector_is_dense v as it would be in your case, but svector_is_dense v0.

By the way, in the second constructor, I guess you meant Vector.tl v0 and svector_tl_dense D0. Here is the full term I wrote (don't mind the additionnal _ in cons, I don't have implicits activated):

Fixpoint vector_from_svector {A} {n} {v:svector A n} (D:svector_is_dense v): Vector.t A n :=
  match n return forall (w:svector A n), (svector_is_dense w) -> (Vector.t A n) with
  | O => fun _ _ => @Vector.nil A
  | (S p) => fun v0 D0 => Vector.cons _
                            (svector_hd v0 D0) _
                            (vector_from_svector (svector_tl_dense D0))
  end v D.