Library ConfluencebyZofGeneralisedLocalDeBruijninCoq

Confluence by Z of Generalised Local De Bruijn in Coq. Vincent van Oostrom. oostrom@javakade.nl. www.javakade.nl
Constructive confluence is derived from the Z-property (vO, FSCD 2021) for the rewrite system having as objects generalised De Bruijn terms (Bird & Paterson, JFP 1999) in a local representation (simplified from David & Guillaume, MSCS 2001), and as steps beta, decomposed into minimal scope extrusion and substitution, exs and sub (vO & van der Looij & Zwitserlood, ALPS 2004).
Developed with CoqIDE in Coq 8.16.1 on Mac OS X. December 2022. Minimally commented version. Comments welcome.
For the ideas on which this formalisation is based, see De Bruijn, KNAW 1972, Berkling, GMD 1976, Huet JFP 1994, the works mentioned above, (Hendriks & vO, CADE 2003), and (vO & de Vrijer, Chapter 8 of Terese 2003). The lemmata governing the interaction between minimal scope extrusion and substitution are novel, afaik, though they were already established in (Huet JFP 1994) for, what we would call, maximal scope extrusion and substitution, called lift_rec and subst_rec there, on ordinary De Bruijn terms (and multisteps), that is on generalised local De Bruijn terms where the end-of-scopes occur only on top of the variable (only var may have a non-zero number of end-of-scopes).
This work is licensed under the Creative Commons Attribution 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by/4.0/.
  • enable ssreflect tactics
From Coq Require Import ssreflect ssrfun ssrbool.
  • to extract Haskell confluence function
From Coq Require Import Extraction.
Set Implicit Arguments.
Unset Strict Implicit.
Unset Printing Implicit Defensive.
  • scopes as unary natural numbers
Require Import Nat.
  • automatic scope comparisons via lia
Require Import Psatz.
  • move between bool and Prop for equality and comparison of scopes / nats
Require Import PeanoNat.
Require Import Compare_dec.
  • using x_equation coming from Function x to avoid (some) boiler plate code
Require Import FunInd.
Section ConfluencebyZofGeneralisedLocalDeBruijninCoq.
objects of rewrite system: generalised local De Bruijn terms, with operations for beta and bullet function for Z
Inductive lam :=
| var : nat -> lam
| abs : nat -> lam -> lam
| app : nat -> lam -> lam -> lam.
Function eos (t : lam) : nat :=
match t with
| var i => i
| abs i _ => i
| app i _ _ => i
end.
Function dcs (t:lam) : lam :=
match t with
| var i => var (i-1)
| abs i s => abs (i-1) s
| app i s u => app (i-1) s u
end.
Function ads (n:nat) (t:lam) : lam :=
match t with
| var i => var (i+n)
| abs i s => abs (i+n) s
| app i s u => app (i+n) s u
end.
extrusion and substitution as in vO & vdL & Z 2004
Fixpoint exs1 (t:lam)(d:nat){struct t} : lam :=
if d <=? (eos t) then ads 1 t else
match t with
| var i => var i
| abs i s => abs i (exs1 s (S (d - (eos t))))
| app i s u => app i (exs1 s (d - (eos t))) (exs1 u (d - (eos t)))
end.
Function exs (n:nat)(d:nat)(t:lam) : lam :=
match n with
| 0 => t
| S m => exs m d (exs1 t d)
end.
Function sub (d:nat)(t:lam) (s:lam) : lam :=
let j := eos t in if j <=? d then let e := d - j in match t with
  | var i => if j =? d then ads i s else t
  | abs i u => abs i (sub (S e) u s)
  | app i u v => app i (sub e u s) (sub e v s)
end else dcs t.
Definition beta (n:nat) (t s:lam) :=
  sub 0 (exs n 1 t) s.
bullet a la Loader, LFCS University of Edinburgh 1997
Function bul (t : lam) : lam :=
match t with
| app i (abs j s) u => ads i (beta j (bul s) (bul u))
| var i => var i
| abs i s => abs i (bul s)
| app i s u => app i (bul s) (bul u)
end.
interaction between operations as conditional rewrite rules.
conditions on end-of-scopes as constraints on nats
Lemma eosads : forall (n:nat)(t:lam), eos (ads n t) = eos(t) + n.
move=> n t. case t; intuition. Qed.
Lemma eosexs1 : forall (t:lam)(d e:nat), e <= eos t -> e <= eos (exs1 t d).
move=>t d; case t; simpl; move=> m *; case (d <=? m); simpl; lia. Qed.
Lemma eosexs : forall (n:nat)(t:lam)(d e:nat), e <= eos t -> e <= eos (exs n d t).
induction n=>t d e H; [| rewrite exs_equation; apply IHn ; apply eosexs1]; auto. Qed.
Lemma eosbul : forall (t:lam)(n:nat), n <= eos t -> n <= eos (bul t).
move=>t; case t; [auto|auto|].
move=> n l; case l; [auto|move=>i u v j;simpl; rewrite eosads=>H;lia|auto]. Qed.
Ltac eqs :=
    try (apply eosbul; first by eqs);
    try (apply eosexs; first by eqs);
    try (apply eosexs1; first by eqs);
    try rewrite eosads;
    trivial;
    try lia;
    try (f_equal; lia);
    try (f_equal;f_equal;lia);
    try simpl in *;
    f_equal;f_equal;f_equal;lia.
preliminary rewrite rules on interaction (should be automatable)
Lemma dcsvar : forall (i: nat), dcs (var i) = var (i-1). auto. Qed.
Lemma dcsabs : forall (i: nat)(t:lam), dcs (abs i t) = abs (i-1) t. auto. Qed.
Lemma dcsapp : forall (i: nat)(t s:lam), dcs (app i t s) = app (i-1) t s. auto. Qed.
Lemma dcsadsn : forall (n:nat)(t:lam), n > 0 -> dcs (ads n t) = ads (n-1) t.
move=> n t. case t; simpl; move=> *; eqs. Qed.
Lemma dcsadst : forall (t:lam)(n:nat), eos t > 0 -> dcs (ads n t) = ads n (dcs t).
move=> t n. case t; simpl; move=> *; eqs. Qed.
Lemma adsvar : forall (n i: nat), ads n (var i) = var (i+n). auto. Qed.
Lemma adsabs : forall (n i: nat)(t:lam), ads n (abs i t) = abs (i+n) t. auto. Qed.
Lemma adsapp : forall (n i: nat)(t s:lam), ads n (app i t s) = app (i+n) t s. auto. Qed.
Lemma adszer : forall (t:lam)(n:nat), n = 0 -> ads n t = t.
move=> t. case t; move=>* ; subst; eqs. Qed.
Lemma adsads : forall (n m:nat)(t:lam),
  ads m (ads n t) = ads (n+m) t.
move=> n m t. case t;move=> *; simpl; f_equal; lia. Qed.
Lemma exs1_equation : forall (t : lam) (d : nat), exs1 t d =
if d <=? eos t then ads 1 t else
match t with
| var i => var i
| abs i s => abs i (exs1 s (S (d - eos t)))
| app i s u => app i (exs1 s (d - eos t)) (exs1 u (d - eos t))
end.
move =>t. case t; intuition. Qed.
Lemma exsle : forall (n d:nat)(t:lam), d <= eos t ->
  exs n d t = ads n t.
induction n => d t H; rewrite exs_equation.
+ rewrite adszer; trivial.
+ rewrite IHn; [ apply eosexs1 |
  rewrite exs1_equation; rewrite leb_correct; last rewrite adsads ]; trivial.
Qed.
Lemma exslevar : forall (n d:nat)(i:nat), d <= i -> exs n d (var i) = var (i+n).
move => *. rewrite exsle; auto. Qed.
Lemma exsleabs : forall (n d:nat)(i:nat)(t:lam), d <= i -> exs n d (abs i t) = abs (i+n) t.
move => *. rewrite exsle; auto. Qed.
Lemma exsleapp : forall (n d:nat)(i:nat)(t s:lam), d <= i -> exs n d (app i t s) = app (i+n) t s.
move => *. rewrite exsle; auto. Qed.
Lemma exsleads : forall (n d:nat)(i:nat)(t:lam), d <= i -> exs n d (ads i t) = ads (i+n) t.
move => *. rewrite exsle; first eqs; rewrite adsads; trivial. Qed.
Lemma exsgt : forall (n d:nat)(t:lam), ~d <= eos t ->
  exs n d t = match t with
  | (var i) => var i
  | (abs i t) => abs i (exs n (S (d-i)) t)
  | (app i t s) => app i (exs n (d-i) t) (exs n (d-i) s)
  end.
induction n => d t H; rewrite exs_equation.
+ case t; trivial.
+ rewrite exs1_equation. rewrite leb_correct_conv; first lia.
  move: H. case t=>*; (rewrite IHn; simpl in *; [trivial | f_equal]).
Qed.
Lemma exsgtvar : forall (n d:nat)(i:nat), ~d <= i -> exs n d (var i) = var i.
move => *. rewrite exsgt; auto. Qed.
Lemma exsgtabs : forall (n d:nat)(i:nat)(t:lam), ~d <= i -> exs n d (abs i t) =
  abs i (exs n (S (d-i)) t).
move => *. rewrite exsgt; auto. Qed.
Lemma exsgtapp : forall (n d:nat)(i:nat)(t s:lam), ~d <= i -> exs n d (app i t s) =
  app i (exs n (d-i) t) (exs n (d-i) s).
move => *. rewrite exsgt; auto. Qed.
Lemma sublt : forall (t:lam)(d:nat)(s:lam), d < eos t ->
  sub d t s = dcs t.
move=> t d s. case t;simpl;move=>*; (rewrite leb_correct_conv; [lia|trivial]). Qed.
Lemma subgtvar : forall (j d:nat)(s:lam), j < d ->
  sub d (var j) s = (var j).
move=> j d s H; simpl; rewrite leb_correct; first lia.
  have : (j =? d) = false by apply Nat.eqb_neq; first lia.
  move=> R; rewrite R; trivial. Qed.
Lemma subeqvar : forall (j d:nat)(s:lam), j = d ->
  sub d (var j) s = ads j s.
move =>*; simpl; rewrite leb_correct; [ lia | subst; rewrite Nat.eqb_refl; trivial]. Qed.
Lemma subgeabs : forall (j d:nat)(t s:lam), j <= d ->
  sub d (abs j t) s = abs j (sub (S (d-j)) t s).
move=>*; simpl; rewrite leb_correct; [lia | trivial]. Qed.
Lemma subgeapp : forall (j d:nat)(t u s:lam), j <= d ->
  sub d (app j t u) s = app j (sub (d-j) t s) (sub (d-j) u s).
move=>*. simpl. rewrite leb_correct; [ lia | trivial]. Qed.
Lemma bulbet : forall (i j:nat)(s u:lam), bul (app i (abs j s) u) =
  ads i (beta j (bul s) (bul u)). auto. Qed.
Lemma bulvar : forall (i:nat), bul (var i) = var i. auto. Qed.
Lemma bulabs : forall (i:nat)(s:lam), bul (abs i s) = abs i (bul s). auto. Qed.
Lemma bulappvar : forall (i j:nat)(u:lam), bul (app i (var j) u) =
  app i (var j) (bul u). auto. Qed.
Lemma bulappapp : forall (i j:nat)(s u v:lam), bul (app i (app j s v) u) =
  app i (bul (app j s v)) (bul u). auto. Qed.
Create HintDb gldb.
Hint Rewrite dcsvar dcsabs dcsapp
  adsvar adsabs adsapp adsads
  bulbet bulvar bulabs bulappvar bulappapp : gldb.
Hint Rewrite adszer dcsadsn dcsadst
  exslevar exsleabs exsleapp exsleads exsgtvar exsgtabs exsgtapp exsle
  sublt subgtvar subeqvar subgeabs subgeapp using eqs : gldb.
Ltac nf := autorewrite with gldb in *; try eqs.
Lemma subgeads : forall (t:lam)(i k:nat), i <= k -> forall (s:lam),
  sub k (ads i t) s = ads i (sub (k-i) t s).
move=> t i k. destruct (le_dec (i+(eos t)) k) as [Hle | Hgt ];
  [ move: Hle; case t=> n *; [ destruct (Nat.eq_dec (i+n) k) | |] | move =>*]; nf.
Qed.
main rewrite rules on interaction
Lemma dcsexs : forall (t: lam)(d n:nat), d > 0 -> 0 < eos t ->
  dcs (exs n d t) = exs n (d-1) (dcs t).
move=> t d n Hd.
case t=>i;(case i=>[*|j *]; simpl in * |-;[lia|]); (elim (le_dec d (S j)) => * ); nf. Qed.
Lemma exsads : forall (t:lam)(i d k:nat), ~(d <= i) ->
  exs k d (ads i t) = ads i (exs k (d-i) t).
move=> t i d k Hd. elim (le_dec (d-i) (eos t)); case t; move =>*; nf. Qed.
Lemma dcsbul : forall (t:lam), eos t > 0 ->
  dcs (bul t) = bul (dcs t).
move=> t. case t; [ | | move => n u; case u]; move => *; nf. Qed.
Lemma bulads : forall (t:lam)(n:nat),
  bul (ads n t) = ads n (bul t).
move=> t. case t; [ | | move => n u; case u]; move => *; nf. Qed.
Hint Rewrite dcsexs exsads subgeads dcsbul using eqs : gldb.
Hint Rewrite <- bulads : gldb.
Lemma exsbelowexs : forall (t:lam)(e d k m:nat), d < e ->
  exs m d (exs k e t) = exs k (e+m) (exs m d t).
move=> t. elim t => [ i | i s IHs | i s IHs u IHu ]; move=> e d k m H;
  (destruct (le_dec d i); [ destruct (le_dec e i) |]; nf); f_equal;
  [ rewrite IHs | rewrite IHs | rewrite IHu] ; eqs.
Qed.
Lemma exsinexs : forall (e:nat)(t:lam)(d k m:nat), e <= m ->
  exs (k+m) d t = exs k (d+e) (exs m d t).
move=> e t. elim t => [ i | i s IHs | i s IHs u IHu ]; move=> d k m H;
 (destruct (le_dec d i); nf); f_equal;
 [ rewrite IHs | rewrite IHs | rewrite IHu] ; eqs.
Qed.
Lemma subaboveexs : forall (t s : lam) (i j k : nat), j > i ->
  exs k j (sub i t s) = sub i (exs k (S j) t) (exs k (j - i) s).
induction t=> s i j k H; (destruct (le_dec n i); nf); f_equal;
  [ destruct (Nat.eq_dec n i) | rewrite IHt | rewrite IHt1 | rewrite IHt2]; nf.
Qed.
Lemma subbelowexs : forall (t s : lam) (i j k : nat), j <= i ->
  exs k j (sub i t s) = sub (i+k) (exs k j t) s.
induction t => s i j k H;(destruct (le_dec n i);nf); (destruct (le_dec j n);nf); f_equal;
  [ destruct (Nat.eq_dec n i) | rewrite IHt | rewrite IHt1 | rewrite IHt2]; nf.
Qed.
Lemma subinexs : forall (k:nat)(u t: lam)(j d : nat), k < j ->
  exs (j-1) d t = sub (k+d) (exs j d t) u.
move => k u t. induction t => j d H; (destruct (le_dec d n); nf); f_equal;
  [ rewrite IHt | rewrite IHt1 | rewrite IHt2 ]; eqs.
Qed.
TLFKASL; self-distributivity of substitution; cf. Schikora, MSc thesis, CL, Innsbruck, 2022. The Lemma Formerly Known As Substitution Lemma (Barendregt, 1984)
Lemma subsub : forall (u t s: lam)(e d : nat), d <= e ->
  sub d (sub (S e) t u) (sub (e - d) s u) =
  sub e (sub d t s) u.
move => u t. induction t => s e d H; (destruct (le_dec n d); [ |
  rewrite -> sublt with (s:=s); nf ; destruct (le_dec n (S e));
  try (rewrite -> sublt with (d:=S e); last eqs)]; nf);
  [ destruct (Nat.eq_dec n d); nf; rewrite subgeads
  | destruct (Nat.eq_dec n (S e)) | f_equal; rewrite <- IHt
  | f_equal; [rewrite <- IHt1 | rewrite <- IHt2]]; nf.
Qed.
Hint Rewrite <- subinexs using eqs : gldb.
Hint Rewrite exsbelowexs subbelowexs subaboveexs using eqs : gldb.
Hint Rewrite <- subsub using eqs : gldb.
Hint Rewrite <- exsinexs using eqs : gldb.
Lemma exsbul : forall (t : lam) (d n: nat),
  exs n d (bul t) = bul (exs n d t).
induction t => d m; (destruct (le_dec d n); nf).
+ f_equal; rewrite IHt; nf.
+ move: IHt1. case t1 => [i IHt1 | i t IHt1 | i t s IHt1]; nf;
  try (rewrite IHt1; rewrite IHt2;nf);
  (destruct (le_dec (d-n) i); nf; unfold beta; nf); rewrite <- IHt2; [
    replace (S (d - n)) with (1+(d-n)); nf | ].
  f_equal; f_equal; last eqs.
  have : exs m (d-n) (bul (abs i t)) = bul (exs m (d-n) (abs i t)) by apply IHt1.
  nf. move=>IHt1'. inversion IHt1'. symmetry. nf.
Qed.
Hint Rewrite exsbul : gldb.
Ltac rnf := nf; auto with gldb.
beta steps of rewrite system, and (derived) reductions, as proof terms
Inductive step : lam -> lam -> Set :=
| sbeta (i j:nat) (t s:lam) : step (app i (abs j t) s) (ads i (beta j t s))
| sabs (i:nat) (t s:lam) : step t s -> step (abs i t) (abs i s)
| sapp1 (i:nat) (t s u:lam) : step t s -> step (app i t u) (app i s u)
| sapp2 (i:nat) (t s u:lam) : step t s -> step (app i u t) (app i u s).
reductions as either non-empty compositions or empty, so that empty steps do not proliferate
Inductive nred : lam -> lam -> Set :=
| nstep (t s:lam) : step t s -> nred t s
| ntrans (t s u:lam) : nred t s -> nred s u -> nred t u.
Inductive red : lam -> lam -> Set :=
| rrefl (t : lam) : red t t
| rnred (t s:lam) : nred t s -> red t s.
Hint Resolve sbeta sabs sapp1 sapp2 nstep rrefl rnred: gldb.
we have a term rewrite system: compatible, closed under substitutions, coherent
Definition rstep (t s:lam)(S:step t s): red t s := rnred (nstep S).
Definition rtrans t s u (R1 : red t s) : red s u -> red t u :=
match R1 in (red x1 y1) return (red y1 u -> red x1 u) with
| rrefl t1 => fun (R2 : red t1 u) => R2
| @rnred t1 s1 N1 => fun (R2 : red s1 u) =>
  match R2 in (red x2 y2) return (nred t1 x2 -> red t1 y2) with
  | rrefl t2 => rnred (s:=t2)
  | @rnred t2 s2 N2 => (fun (n3 : nred t1 t2) => rnred (ntrans n3 N2))
  end N1
end.
Lemma srr : forall (f: lam -> lam),
  (forall (t s:lam), step t s -> red (f t) (f s)) ->
  forall (t s:lam), red t s -> red (f t) (f s).
move=> f H t s N. destruct N; rnf.
induction n; rnf.
apply rtrans with (s:=f s); [ exact IHn1 | exact IHn2 ].
Defined.
Lemma ssr : forall (f: lam -> lam),
  (forall (t s:lam), step t s -> step (f t) (f s)) ->
  forall (t s:lam), red t s -> red (f t) (f s).
move=> f S; apply srr; move=> t s T; rnf. Defined.
Lemma betatgt : forall (i j:nat)(t s u:lam),
  ads i (beta j t s) = u -> step (app i (abs j t) s) u.
move=> i j t s u H.
rewrite <- H; apply sbeta.
Defined.
Lemma ncrabsfw : forall (s t:lam), nred s t -> forall (i:nat)(u:lam), s = abs i u ->
  { v : lam & { r : nred u v | t = abs i v}}.
move=> s t N. induction N => i x I;subst.
+ inversion s0; subst.
  exists s1, (nstep H2); trivial.
+ have : {v : lam & {_ : nred x v | s = abs i v}} by apply IHN1; trivial.
  move=>H1. destruct H1 as (w & I & J); subst.
  have : {v : lam & {_ : nred w v | u = abs i v}} by apply IHN2; trivial.
  move=>H1. destruct H1 as (y & K & L); subst.
  exists y, (ntrans I K); trivial.
Defined.
Lemma sads : forall (i:nat) (t s:lam),
  step t s -> step (ads i t) (ads i s).
move=> i t s H. inversion H; rnf. Defined.
Lemma nrapp1 : forall (i :nat) (t s u:lam), nred t s -> nred (app i t u) (app i s u).
move=> i t s u N. induction N; rnf. apply ntrans with (app i s u); trivial. Defined.
Lemma nrapp2 : forall (i :nat) (t s u:lam), nred t s -> nred (app i u t) (app i u s).
move=> i t s u N. induction N; rnf. apply ntrans with (app i u s); trivial. Defined.
Hint Resolve sads nrapp1 nrapp2 : gldb.
Lemma rabs : forall (i :nat) (t s:lam), red t s -> red (abs i t) (abs i s).
move=> i t s R. destruct R as [|t s N]; [apply rrefl |apply rnred].
induction N; rnf. apply ntrans with (abs i s); trivial. Defined.
Lemma rads : forall (i:nat)(t s:lam), red t s ->
  red (ads i t) (ads i s).
move=> i; apply ssr with (f := fun u => ads i u); rnf. Defined.
Lemma rapp1 : forall (i :nat) (t s u:lam), red t s -> red (app i t u) (app i s u).
move=> i t s u R. destruct R; rnf.
Defined.
Lemma rapp2 : forall (i :nat) (t s u:lam), red t s -> red (app i u t) (app i u s).
move=> i t s u R. destruct R; rnf. Defined.
Hint Resolve rabs rapp1 rapp2 rads: gldb.
Lemma crabsfw : forall (s t:lam), red s t -> forall (i:nat)(u:lam), s = abs i u ->
  { v : lam & { r : red u v | t = abs i v}}.
move=> s t R. destruct R => i x N;subst.
+ exists x, (rrefl x). trivial.
+ have : { v : lam & { r : nred x v | s = abs i v}} by apply ncrabsfw with (s:=abs i x); trivial.
  move=>H1. destruct H1 as (w & I & J); subst.
  exists w, (rnred I); trivial.
Defined.
Lemma crabs : forall (i:nat)(u v:lam), red (abs i u) (abs i v) ->
  red u v.
move=> i u v R.
have : { v0 : lam & { r : red u v0 | abs i v = abs i v0}} by
  apply crabsfw with (s:=abs i u)(t:=abs i v)(i:=i)(u:=u).
move=>H. destruct H as (x & I & J); subst.
inversion J; trivial.
Defined.
Lemma rapp : forall (i :nat) (t s u v:lam), red t s -> red u v -> red (app i t u) (app i s v).
move=> i t s u v R1 R2. apply rtrans with (app i s u); rnf. Defined.
Hint Resolve rapp crabs: gldb.
Lemma sexs : forall (t s:lam), step t s -> forall (d k:nat),
  step (exs k d t) (exs k d s).
move=> t s S. induction S => d k; destruct (le_dec d i); rnf.
destruct (le_dec (d-i) j); nf; apply betatgt; f_equal; unfold beta; nf.
replace (S (d-i)) with (1+(d-i)); nf.
Defined.
Lemma sbsub : forall (t s:lam), step t s -> forall (i:nat)(u:lam),
  step (sub i t u) (sub i s u).
move=> t s S. induction S => k v; destruct (le_dec i k);rnf; destruct (le_dec j (k - i));rnf;
apply betatgt; unfold beta;rnf. f_equal; (f_equal;last eqs).
replace (S (k - i)) with ((k-i)+1);rnf.
Defined.
Lemma sasub : forall (t:lam)(i:nat)(u v:lam), step u v ->
  red (sub i t u) (sub i t v).
induction t=> i u v S; destruct (le_dec n i); rnf.
destruct (Nat.eq_dec n i); rnf.
Defined.
Hint Resolve sexs sasub sbsub: gldb.
Lemma rexs : forall (d i:nat)(t s:lam), red t s ->
  red (exs i d t) (exs i d s).
move=> d i; apply ssr with (f:= fun u => exs i d u); rnf. Defined.
Lemma rbsub : forall (i:nat)(u t s:lam), red t s ->
  red (sub i t u) (sub i s u).
move=> i u; apply ssr with (f:= fun v => sub i v u); rnf. Defined.
Lemma rasub : forall (i:nat)(t u v:lam), red u v ->
  red (sub i t u) (sub i t v).
move=> i t; apply srr with (f:= fun s => sub i t s); rnf. Defined.
Hint Resolve rexs rasub rbsub: gldb.
Lemma rsub : forall (t s u v:lam), red t s -> red u v -> forall (i:nat),
  red (sub i t u) (sub i s v).
move=> t s u v S R i; apply rtrans with (s:= sub i t v); rnf. Defined.
Hint Resolve rsub: gldb.
Lemma rbeta : forall (t s u v:lam), red t s -> red u v -> forall (j:nat),
  red (beta j t u) (beta j s v).
move=> t s u v S R j. unfold beta. rnf. Defined.
Hint Resolve rbeta: gldb.
wrt the bullet map the rewrite system is extensive, has the rhs property, and has Z (upperbound and monotonic)
Lemma extensive : forall t:lam, red t (bul t).
induction t; rnf.
move: IHt1; destruct t1 as [| m s |]; move =>*; rnf.
have : red s (bul s) by apply crabs with (i:=m). move => IHs.
apply rtrans with (ads n (beta m s t2)); rnf.
Defined.
cf. the Nominal Isabelle formalisation of Z, Felgenhauer & Nagele & vO & Sternagel IWC 2016
Lemma appbul : forall (t s:lam)(i:nat),
  red (app i (bul t) (bul s)) (bul (app i t s)).
move=>t. destruct t; move=>*; rnf. Defined.
Hint Resolve extensive appbul: gldb.
Lemma rhs : forall (t s:lam)(d:nat),
  red (sub d (bul t) (bul s)) (bul (sub d t s)).
induction t => s d; destruct (le_dec n d) as [Hle | Hgt]; rnf;
[ destruct (Nat.eq_dec n d); rnf | ].
move: IHt1. case t1 => [ m IHt1 | m t IHt1 | m t u IHt1]; rnf.
+ apply rtrans with (app n (bul (sub (d-n) (var m) s)) (bul (sub (d-n) t2 s))); rnf.
+ destruct (le_dec m (d-n)) as [Ble | Bgt]; rnf.
  - apply rads.
    have : (sub (d-n) (beta m (bul t) (bul t2)) (bul s)) =
      (beta m (sub (S (d - n - m)) (bul t) (bul s))
      (sub (d-n) (bul t2) (bul s))).
    * unfold beta. rnf.
    * move=> H. rewrite H.
      apply rbeta; [|apply IHt2].
      have : red (sub (d-n) (bul (abs m t)) (bul s))
        (bul (sub (d-n) (abs m t) s)) by apply IHt1.
      nf.
      move=> IHt1dn. apply crabs in IHt1dn.
      auto.
  - rewrite [sub _ (abs _ _ ) _]sublt; nf.
    apply rads.
    have : (sub (d - n) (beta m (bul t) (bul t2)) (bul s)) =
      (beta (m - 1) (bul t) (sub (d-n) (bul t2) (bul s))).
    * unfold beta. nf. f_equal; last eqs. rewrite <- exsbul.
    replace (S (d-n)) with ((d-n)+1); last lia.
    rewrite <- subinexs; rnf.
    * move=> H. rewrite H. rnf.
+ apply rtrans with (app n (bul (sub (d-n) (app m t u) s)) (bul (sub (d-n) t2 s))); rnf.
Defined.
Lemma upperbound : forall (t s:lam), step t s -> red s (bul t).
induction t => s S; [| | move: IHt1 S; case t1 =>
  [ i IHt1 S | i t IHt1 S | i t u IHt1 S]]; inversion S; subst;rnf.
+ inversion H3;subst.
  have : red s (bul t) by apply crabs with (i:=i); apply IHt1. move => *.
  apply rtrans with (ads n (beta i s t2)) ; rnf.
+ apply rtrans with (ads n (beta i t s0)) ; rnf.
Defined.
Hint Resolve rhs upperbound : gldb.
Lemma monotonic : forall (t s:lam), step t s -> red (bul t) (bul s).
induction t => s S; [| | move: IHt1 S; case t1 =>
  [ i IHt1 S | i t IHt1 S | i t u IHt1 S]]; inversion S; subst;rnf.
+ inversion H3.
+ rewrite bulads. apply rads. unfold beta. rnf.
+ inversion H3; subst. nf. apply rads.
  have : red (bul t) (bul s) by apply crabs with (i:=i); apply IHt1 with (s:= abs i s). move => *.
  rnf.
+ apply rtrans with (s:= app n (bul s0) (bul t2)) ; rnf.
Defined.
Hint Resolve monotonic : gldb.
(constructive) confluence from the Z-property via the Strip Lemma
Lemma rmonotonic : forall (t s:lam), red t s -> red (bul t) (bul s).
apply srr with (f:= bul). rnf. Defined.
Hint Resolve rmonotonic : gldb.
Lemma stripZ : forall (t s u:lam), (step t s) -> (red t u) ->
  { v:lam & red s v & red u v }.
move=> t s u R1 R2. exists (bul u); [ apply rtrans with (bul t) |]; rnf. Defined.
Theorem confluence : forall (t s:lam), (red t s) -> forall (u:lam), (red t u) ->
  { v:lam & red s v & red u v }.
move=>t s R1.
destruct R1.
+ move=> x R2. exists x; rnf.
+ induction n => x R2.
  - apply stripZ with (t:=t); trivial.
  - have : {w : lam & red s w & red x w} by apply IHn1; trivial.
    move=> H. destruct H as [y].
    have : {w : lam & red u w & red y w} by apply IHn2; trivial.
    move=> H. destruct H as [z].
    exists z; [ exact r1 | apply (rtrans r0 r2)].
Defined.
End ConfluencebyZofGeneralisedLocalDeBruijninCoq.
Extraction Language Haskell.
Extraction "/Users/oostromgestolen/Desktop/ConfluencebyZofGeneralisedLocalDeBruijninCoqExtracted" confluence.
Haskell extraction needs boiler plate code to interact with the confluence function; DIY