Library FingerTree.FingerTree

Une interface non dépendante



Comme décrit précédemment, on peut agréger la mesure et le fingertree dans une paire dépendante pour donner une interface simplifiée aux dépendants.

Section FingerTree.
  Context `(ma : Measured v A).
  Definition FingerTree := { m : v & fingertree v A m }.
  Notation " ts :| t " := (existT _ ts t) (at level 20).

Cela nous donne un type FingerTree v {mono} A {ma}, qu'on peut comparer au type original dans . On a ajouté l'implémentation monoid et la fonction de mesure ma comme paramètres explicites alors qu'en ils sont passés implicitement à l'aide des classes de type à chaque fonction les manipulant.

On ne décrit pas le "repackaging" en détail, il s'agit just de décomposer un objet de type FingerTree, appeler la fonction appropriée sur les fingertree et recomposer la paire dépendante. En revanche un point important est que l'on peut exporter les vues sur les fingertree et retrouver la mesure associée:

  Program Definition tree_size (s : FingerTree) : nat :=
    let '_ :| t := s in tree_size t.

  Inductive left_view : Type :=
  | nil_left : left_view | cons_left : A -> FingerTree -> left_view.

  Lemma view_left_size : forall t x t', view_left t = cons_left x t' ->
    tree_size t' < tree_size t.
  Proof.
    intros.
    destruct t ; destruct t' ; simpl in *.
    generalize H ; clear H.
    remember (view_L f) as vf.
    destruct vf ; simpl in * ; intros ; try discriminate.
    symmetry in Heqvf.
    pose (view_L_size_measure f Heqvf).
    inversion H.
    subst.
    assert(Hi:=inj_pairT2 H3).
    subst f0.
    simpl.
    omega.
  Qed.

On peut aussi refaire le découpage par rapport à un prédicat sur les FingerTree. On offre la même interface simplement typée qu'en en définissant la fonction split_with p x. Cette fonction découpe n'importe quel arbre en regardant tout d'abord s'il est vide et sinon en appelant la fonction fortement spécifiée split avec un accumulateur vide ε. On crée alors une paire avec l'arbre à gauche et l'arbre droit auquel on ajoute l'élément qui fait changer le prédicat de valeur. On oublie complètement les propriétés données par la fonction split sur le résultat.

    Program Definition split_with (p : v -> bool)
      (x : FingerTree) : FingerTree * FingerTree :=
      if is_empty_dec x then (empty, empty)
      else let (l, x, r) := split p ε x in (l, cons x r).

End FingerTree.