Library ListFromRight.rl

Author: Jean-François Monin, Verimag, Université Grenoble Alpes
List traversal from right to left: basic definitions to be used in foldl.v, in particular an inductive domain for termination certificates, with its projection and small inversions.
Contains improvements on material provided with D. Larchey-Wendling in our chapter on the Braga Method (2021)

Require Import Utf8.

Require Import List.
Import ListNotations.

Reserved Notation "x '+:' y" (at level 59, left associativity, format "x +: y").

Fixpoint consr {A} (l : list A) (y : A) { struct l } : list A :=
  match l with
  | [][y]
  | x :: lx :: l +: y
  end
where "x +: y" := (consr x y) : list_scope.

Inductive rl {A: Type} : list A Type :=
| Nilr : rl []
| Consr : u z, rl (u +: z)
.

Section sec_context.

Context {A: Type}.
Implicit Type l u v : list A.
Implicit Type x y z : A.

Reflection function
Fixpoint l2r l : rl l :=
  match l with
  | []Nilr
  | x :: v
     match l2r v with
     | NilrConsr [] x
     | Consr u zConsr (x :: u) z
     end
  end.

Basic but key lemma. This is a proven equality, NOT a conversion.
Lemma l2r_consr : u z, l2r (u +: z) = Consr u z.
Proof.
  intros u z; induction u as [ | x u Hu]; simpl.
  - reflexivity.
  - rewrite Hu. reflexivity.
Qed.


Inductively defined domain
Original version mentioned in the chapter on the Braga method (2021)
                      𝔻listz u
  ----------      ----------------
  𝔻listz []       𝔻listz (u +: z)


Translated here as follows using rl, a dependent type:

                             𝔻listz u (l2r u)
  ---------------      ----------------------------
  𝔻listz [] Nilr       𝔻listz (u +: z) (Consr u z)

Unset Elimination Schemes.
Inductive 𝔻listz : {l}, rl l Prop :=
| 𝔻Nilr : 𝔻listz Nilr
| 𝔻Consr : u z, 𝔻listz (l2r u) 𝔻listz (Consr u z)
.

Small inversion
Inductive is_𝔻Nilr : 𝔻listz Nilr Prop :=
| is_𝔻Nilr_intro : is_𝔻Nilr 𝔻Nilr.
Inductive is_𝔻Consr u z : 𝔻listz (Consr u z) Prop :=
| is_𝔻Consr_intro (d : 𝔻listz (l2r u)) : is_𝔻Consr u z (𝔻Consr u z d).

Definition 𝔻listz_inv {l} {r : rl l} (d : 𝔻listz r) :
  match r with
  | Nilris_𝔻Nilr
  | Consr u zis_𝔻Consr u z
  end d.
Proof. destruct d; constructor. Defined.


Structural projection

Definition π_𝔻listz_Consr {u} {z} (d: 𝔻listz (Consr u z)) : 𝔻listz (l2r u) :=
  match d in 𝔻listz r return
        let shape := match r with Consr u zTrue | _False end in
        let u := match r with Consr u zu | _u end in
        shape 𝔻listz (l2r u) with
  | 𝔻Consr u0 z0 D0λ _, D0
  | _λ fa, match fa with end
  end I.

Smaller inversion
Inductive is_𝔻Consr_π u z (d : 𝔻listz (Consr u z)) : 𝔻listz (Consr u z) Prop :=
| is_𝔻Consr_π_intro: is_𝔻Consr_π u z d (𝔻Consr u z (π_𝔻listz_Consr d)).

Definition 𝔻listz_inv_π {l} {r : rl l} (d : 𝔻listz r) :
  match r with
  | Nilrfun _is_𝔻Nilr
  | Consr u zis_𝔻Consr_π u z
  end d d.
Proof. destruct d; constructor. Defined.


Dependent recursor (improvements on the Braga paper)

Definition 𝔻listz_rect (P: {l} (r : rl l), 𝔻listz r Type) :
  P Nilr 𝔻Nilr ( u z d, P (l2r u) d P (Consr u z) (𝔻Consr u z d))
   l (r: rl l) (d: 𝔻listz r), P r d.
Proof.
  intros Pnil Pconsr.
  refine (fix fxp l r d {struct d} : _ := _).
  revert d.
  destruct r as [| u z]; simpl; intros d.
  - destruct (𝔻listz_inv_π d). apply Pnil.
  - destruct (𝔻listz_inv_π d). apply Pconsr, fxp.
Defined.

The dependent induction principle can be seen as a corollary of 𝔻listz_rect, but it has a simpler and direct proof on d
Definition 𝔻listz_ind (P: {l} (r: rl l), 𝔻listz r Prop) :
  P Nilr 𝔻Nilr ( u z d, P (l2r u) d P (Consr u z) (𝔻Consr u z d))
   l (r : rl l) (d: 𝔻listz r), P r d :=
  fun PNilr PConsr
    fix fxp l r d {struct d} : P r d :=
    match d with
    | 𝔻NilrPNilr
    | 𝔻Consr u z dPConsr u z d (fxp u (l2r u) d)
    end.

Lemma 𝔻listz_all l : 𝔻listz (l2r l).
Proof.
  induction l as [| x v d].
  - exact 𝔻Nilr.
  - induction d as [|u z d IHd].
    + exact (𝔻Consr [] x 𝔻Nilr).
    + change (x :: u +: z) with ((x :: u) +: z); rewrite l2r_consr.
      apply (𝔻Consr (x :: u) z), IHd.
Qed.

End sec_context.