Built with Alectryon, running Coq+SerAPI v8.17.0+0.17.3. Bubbles () indicate interactive fragments: hover for details, tap to reveal contents. Use Ctrl+ā†‘ Ctrl+ā†“ to navigate, Ctrl+šŸ–±ļø to focus. On Mac, use āŒ˜ instead of Ctrl.

Substitution structures (Ā§ 4.1)

In this file we axiomatize what it means for a family to support substitution.

Substitution Monoid (Def. 7)

The specification of an evaluator will be separated in several steps. First we will ask for a family of values, i.e. objects that can be substituted for variables. We formalize well-typed well-scoped substitutions in the monoidal style of Fiore et al and Allais et al. Here we are generic over a notion of context, treating lists and DeBruijn indices in the usual well-typed well-scoped style, but also other similar notions. See Ctx/Abstract.v for more background on notions of variables and contexts and for the categorical presentation of substitution.

Class subst_monoid `{CC : context T C} (val : Famā‚ T C) := {
  v_var : c_var ā‡’ā‚ val ;
  v_sub : val ā‡’ā‚ āŸ¦ val , val āŸ§ā‚ ;
}.
#[global] Notation "v įµ„āŠ› a" := (v_sub v a%asgn) (at level 30).
Notation a_id := v_var.

By pointwise lifting of substitution we can define composition of assignments.

Definition a_comp `{subst_monoid T C val} {Ī“1 Ī“2 Ī“3}
  : Ī“1 =[val]> Ī“2 -> Ī“2 =[val]> Ī“3 -> Ī“1 =[val]> Ī“3
  := fun u v _ i => u _ i įµ„āŠ› v.
#[global] Infix "āŠ›" := a_comp (at level 14) : asgn_scope.

The laws for monoids and modules are pretty straightforward. A specificity is that assignments are represented by functions from variables to values, as such their well-behaved equality is pointwise equality and we require substitution to respect it.

Class subst_monoid_laws `{CC : context T C} (val : Famā‚ T C) {VM : subst_monoid val} := {
  v_sub_proper :: Proper (āˆ€ā‚• Ī“, āˆ€ā‚• _, eq ==> āˆ€ā‚• Ī”, asgn_eq Ī“ Ī” ==> eq) v_sub ;
  v_sub_var {Ī“1 Ī“2 x} (i : Ī“1 āˆ‹ x) (p : Ī“1 =[val]> Ī“2)
    : v_var i įµ„āŠ› p = p _ i ;
  v_var_sub {Ī“ x} (v : val Ī“ x)
    : v įµ„āŠ› a_id = v ;
  v_sub_sub {Ī“1 Ī“2 Ī“3 x} (v : val Ī“1 x) (a : Ī“1 =[val]> Ī“2) (b : Ī“2 =[val]> Ī“3)
   : v įµ„āŠ› (a āŠ› b) = (v įµ„āŠ› a) įµ„āŠ› b ;
} .
T, C: Type
CC: context T C
val: Famā‚ T C
VM: subst_monoid val
H: subst_monoid_laws val
Ī“1, Ī“2: C
x: T
v: val Ī“1 x

Proper (asgn_eq Ī“1 Ī“2 ==> eq) (v_sub v)
T, C: Type
CC: context T C
val: Famā‚ T C
VM: subst_monoid val
H: subst_monoid_laws val
Ī“1, Ī“2: C
x: T
v: val Ī“1 x

Proper (asgn_eq Ī“1 Ī“2 ==> eq) (v_sub v)
now apply v_sub_proper. Qed.

Substitution Module (Def. 8)

Next, we ask for a module over the monoid of values, to represent the configurations of the machine.

Class subst_module `{CC : context T C} (val : Famā‚ T C) (conf : Famā‚€ T C) := {
  c_sub : conf ā‡’ā‚€ āŸ¦ val , conf āŸ§ā‚€ ;
}.
#[global] Notation "c ā‚œāŠ› a" := (c_sub c a%asgn) (at level 30).

Again the laws should not be surprising.

Class subst_module_laws `{CC : context T C} (val : Famā‚ T C) (conf : Famā‚€ T C)
      {VM : subst_monoid val} {CM : subst_module val conf} := {
  c_sub_proper :: Proper (āˆ€ā‚• Ī“, eq ==> āˆ€ā‚• Ī”, asgn_eq Ī“ Ī” ==> eq) c_sub ;
  c_var_sub {Ī“} (c : conf Ī“) : c ā‚œāŠ› a_id = c ;
  c_sub_sub {Ī“1 Ī“2 Ī“3} (c : conf Ī“1) (a : Ī“1 =[val]> Ī“2) (b : Ī“2 =[val]> Ī“3)
    : c ā‚œāŠ› (a āŠ› b) = (c ā‚œāŠ› a) ā‚œāŠ› b ;
} .

T, C: Type
CC: context T C
val: Famā‚ T C
conf: Famā‚€ T C
VM: subst_monoid val
CM: subst_module val conf
H: subst_module_laws val conf
Ī“1, Ī“2: C
c: conf Ī“1

Proper (asgn_eq Ī“1 Ī“2 ==> eq) (c_sub c)
T, C: Type
CC: context T C
val: Famā‚ T C
conf: Famā‚€ T C
VM: subst_monoid val
CM: subst_module val conf
H: subst_module_laws val conf
Ī“1, Ī“2: C
c: conf Ī“1

Proper (asgn_eq Ī“1 Ī“2 ==> eq) (c_sub c)
now apply c_sub_proper. Qed.

Now that we know that our families have a substitution operation and variables, we can readily derive a renaming operation. While we could have axiomatized it, together with its compatibility with substitution, allowing for possibly more efficient implementations, we prefer simplicity and work with this generic implementation in terms of substitution.

Section renaming.
  Context `{CC : context T C} {val : Famā‚ T C} {conf : Famā‚€ T C}.
  Context {VM : subst_monoid val} {VML : subst_monoid_laws val}.
  Context {CM : subst_module val conf} {CML : subst_module_laws val conf}.

By post-composing with the substitution identity, we can embed renamings into assignments.

  Definition r_emb {Ī“ Ī”} (r : Ī“ āŠ† Ī”) : Ī“ =[val]> Ī”
    := fun _ i => v_var (r _ i).
  #[global] Arguments r_emb {_ _} _ _ /.

Renaming is now simply a matter of substituting by the embedded renaming.

  Definition v_ren : val ā‡’ā‚ āŸ¦ c_var , val āŸ§ā‚
    := fun _ _ v _ r => v įµ„āŠ› r_emb r.
  Definition c_ren : conf ā‡’ā‚€ āŸ¦ c_var , conf āŸ§ā‚€
    := fun _ c _ r => c ā‚œāŠ› r_emb r.
  #[global] Arguments v_ren [Ī“ x] v [Ī”] r /.
  #[global] Arguments c_ren [Ī“] v [Ī”] r /.

Finally we can rename assignments on the right.

  Definition a_ren_r {Ī“1 Ī“2 Ī“3} : Ī“1 =[val]> Ī“2 -> Ī“2 āŠ† Ī“3 -> Ī“1 =[val]> Ī“3
    := fun a r => (a āŠ› (r_emb r))%asgn.
  #[global] Arguments a_ren_r _ _ _ _ _ _ /.
End renaming.
#[global] Notation "v įµ„āŠ›įµ£ r" := (v_ren v r%asgn) (at level 14).
#[global] Notation "c ā‚œāŠ›įµ£ r" := (c_ren c r%asgn) (at level 14).
#[global] Notation "a āŠ›įµ£ r" := (a_ren_r a r) (at level 14) : asgn_scope.

Something which we have absolutely pushed under the rug in the paper is a couple more mild technical hypotheses on the substitution monoid of values: since in the eventual guardedness proof we need to case split on whether or not a value is a variable, we need to ask for that to be possible! As such, we need the following additional assumptions:

  • v_var has decidable fibers
  • v_var is injective
  • the fibers of v_var pull back along renamings

These assumptions are named "clear-cut" in the paper (Def. 27).

We first define the fibers of v_var.

Variant is_var `{VM : subst_monoid T C val} {Ī“ x} : val Ī“ x -> Type :=
| Vvar (i : Ī“ āˆ‹ x) : is_var (v_var i)
.

Equations is_var_get `{VM : subst_monoid T C val} {Ī“ x} {v : val Ī“ x} : is_var v -> Ī“ āˆ‹ x :=
  is_var_get (Vvar i) := i .

Which are obviously stable under renamings.

T, C: Type
CC: context T C
val: Famā‚ T C
VM0: subst_monoid val
VM: subst_monoid_laws val
Ī“1, Ī“2: C
r: Ī“1 āŠ† Ī“2
x: T
v: val Ī“1 x

is_var v -> is_var (v įµ„āŠ›įµ£ r)
T, C: Type
CC: context T C
val: Famā‚ T C
VM0: subst_monoid val
VM: subst_monoid_laws val
Ī“1, Ī“2: C
r: Ī“1 āŠ† Ī“2
x: T
v: val Ī“1 x

is_var v -> is_var (v įµ„āŠ›įµ£ r)
T, C: Type
CC: context T C
val: Famā‚ T C
VM0: subst_monoid val
VM: subst_monoid_laws val
Ī“1, Ī“2: C
r: Ī“1 āŠ† Ī“2
x: T
i: Ī“1 āˆ‹ x

is_var (a_id i įµ„āŠ›įµ£ r)
T, C: Type
CC: context T C
val: Famā‚ T C
VM0: subst_monoid val
VM: subst_monoid_laws val
Ī“1, Ī“2: C
r: Ī“1 āŠ† Ī“2
x: T
i: Ī“1 āˆ‹ x

is_var (r_emb r x i)
econstructor. Qed.

At last we define our last assumptions on variables (Def. 28).

Class var_assumptions `{CC : context T C} (val : Famā‚ T C) {VM : subst_monoid val} := {
  v_var_inj {Ī“ x} : injective (@v_var _ _ _ _ _ Ī“ x) ;
  is_var_dec {Ī“ x} (v : val Ī“ x) : decidable (is_var v) ;
  is_var_ren {Ī“1 Ī“2 x} (v : val Ī“1 x) (r : Ī“1 āŠ† Ī“2) : is_var (v įµ„āŠ›įµ£ r) -> is_var v ;
}.

Here we derive a couple helpers around these new assumptions.

Section variables.
  Context `{CC : context T C} {val : Famā‚ T C}.
  Context {VM : subst_monoid val} {VML : subst_monoid_laws val}.
  Context {VA : var_assumptions val}.

  
T, C: Type
CC: context T C
val: Famā‚ T C
VM: subst_monoid val
VML: subst_monoid_laws val
VA: var_assumptions val
Ī“: C
x: T
v: val Ī“ x
p, q: is_var v

p = q
T, C: Type
CC: context T C
val: Famā‚ T C
VM: subst_monoid val
VML: subst_monoid_laws val
VA: var_assumptions val
Ī“: C
x: T
v: val Ī“ x
p, q: is_var v

p = q
T, C: Type
CC: context T C
val: Famā‚ T C
VM: subst_monoid val
VML: subst_monoid_laws val
VA: var_assumptions val
Ī“: C
x: T
v: val Ī“ x
p, q0: is_var v
i: Ī“ āˆ‹ x
w: val Ī“ x
H: w = a_id i
q: is_var w

Vvar i = rew [is_var] H in q
T, C: Type
CC: context T C
val: Famā‚ T C
VM: subst_monoid val
VML: subst_monoid_laws val
VA: var_assumptions val
Ī“: C
x: T
v: val Ī“ x
p, q0: is_var v
i, i0: Ī“ āˆ‹ x
H: a_id i0 = a_id i

Vvar i = rew [is_var] H in Vvar i0
T, C: Type
CC: context T C
val: Famā‚ T C
VM: subst_monoid val
VML: subst_monoid_laws val
VA: var_assumptions val
Ī“: C
x: T
v: val Ī“ x
p, q0: is_var v
i, i0: Ī“ āˆ‹ x
H: a_id i0 = a_id i
H': i0 = i

Vvar i = rew [is_var] H in Vvar i0
now dependent elimination H'; dependent elimination H. Qed.
T, C: Type
CC: context T C
val: Famā‚ T C
VM: subst_monoid val
VML: subst_monoid_laws val
VA: var_assumptions val
Ī“: C
x: T
i: Ī“ āˆ‹ x
p: is_var (a_id i)

p = Vvar i
T, C: Type
CC: context T C
val: Famā‚ T C
VM: subst_monoid val
VML: subst_monoid_laws val
VA: var_assumptions val
Ī“: C
x: T
i: Ī“ āˆ‹ x
p: is_var (a_id i)

p = Vvar i
apply is_var_irr. Qed. Variant is_var_ren_view {Ī“1 Ī“2 x} (v : val Ī“1 x) (r : Ī“1 āŠ† Ī“2) : is_var (v įµ„āŠ›įµ£ r) -> Type := | Vvren (H : is_var v) : is_var_ren_view v r (ren_is_var r H) .
T, C: Type
CC: context T C
val: Famā‚ T C
VM: subst_monoid val
VML: subst_monoid_laws val
VA: var_assumptions val
Ī“1, Ī“2: C
x: T
v: val Ī“1 x
r: Ī“1 āŠ† Ī“2
H: is_var (v įµ„āŠ›įµ£ r)

is_var_ren_view v r H
T, C: Type
CC: context T C
val: Famā‚ T C
VM: subst_monoid val
VML: subst_monoid_laws val
VA: var_assumptions val
Ī“1, Ī“2: C
x: T
v: val Ī“1 x
r: Ī“1 āŠ† Ī“2
H: is_var (v įµ„āŠ›įµ£ r)

is_var_ren_view v r H
rewrite (is_var_irr H (ren_is_var r (is_var_ren v r H))); econstructor. Qed.
T, C: Type
CC: context T C
val: Famā‚ T C
VM: subst_monoid val
VML: subst_monoid_laws val
VA: var_assumptions val
Ī“1, Ī“2: C
r: Ī“1 āŠ† Ī“2
x: T
v: val Ī“1 x
H: is_var v

is_var_get (ren_is_var r H) = r x (is_var_get H)
T, C: Type
CC: context T C
val: Famā‚ T C
VM: subst_monoid val
VML: subst_monoid_laws val
VA: var_assumptions val
Ī“1, Ī“2: C
r: Ī“1 āŠ† Ī“2
x: T
v: val Ī“1 x
H: is_var v

is_var_get (ren_is_var r H) = r x (is_var_get H)
T, C: Type
CC: context T C
val: Famā‚ T C
VM: subst_monoid val
VML: subst_monoid_laws val
VA: var_assumptions val
Ī“1, Ī“2: C
r: Ī“1 āŠ† Ī“2
x: T
i: Ī“1 āˆ‹ x

is_var_get (ren_is_var r (Vvar i)) = r x i
T, C: Type
CC: context T C
val: Famā‚ T C
VM: subst_monoid val
VML: subst_monoid_laws val
VA: var_assumptions val
Ī“1, Ī“2: C
r: Ī“1 āŠ† Ī“2
x: T
i: Ī“1 āˆ‹ x

forall i0 : is_var (a_id i įµ„āŠ›įµ£ r), is_var_get i0 = r x i
T, C: Type
CC: context T C
val: Famā‚ T C
VM: subst_monoid val
VML: subst_monoid_laws val
VA: var_assumptions val
Ī“1, Ī“2: C
r: Ī“1 āŠ† Ī“2
x: T
i: Ī“1 āˆ‹ x
H: is_var (a_id (r x i))

is_var_get H = r x i
now rewrite (is_var_irr H (Vvar (r _ i))). Qed.
T, C: Type
CC: context T C
val: Famā‚ T C
VM: subst_monoid val
VML: subst_monoid_laws val
VA: var_assumptions val
Ī“: C
x: T
v: val Ī“ x
H: is_var v

v = a_id (is_var_get H)
T, C: Type
CC: context T C
val: Famā‚ T C
VM: subst_monoid val
VML: subst_monoid_laws val
VA: var_assumptions val
Ī“: C
x: T
v: val Ī“ x
H: is_var v

v = a_id (is_var_get H)
now destruct H. Qed. End variables.

Finally we end with a couple derived property on assignments.

Section properties.
  Context {T C} {CC : context T C} (val : Famā‚ T C).
  Context {VM : subst_monoid val} {VML : subst_monoid_laws val}.

  
T, C: Type
CC: context T C
val: Famā‚ T C
VM: subst_monoid val
VML: subst_monoid_laws val
Ī“1, Ī“2, Ī“3: C

Proper (asgn_eq Ī“1 Ī“2 ==> asgn_eq Ī“2 Ī“3 ==> asgn_eq Ī“1 Ī“3) a_comp
T, C: Type
CC: context T C
val: Famā‚ T C
VM: subst_monoid val
VML: subst_monoid_laws val
Ī“1, Ī“2, Ī“3: C

Proper (asgn_eq Ī“1 Ī“2 ==> asgn_eq Ī“2 Ī“3 ==> asgn_eq Ī“1 Ī“3) a_comp
intros ?? H1 ?? H2 ??; cbn; now rewrite H1, H2. Qed.
T, C: Type
CC: context T C
val: Famā‚ T C
VM: subst_monoid val
VML: subst_monoid_laws val
Ī“1, Ī“2: C

Proper (asgn_eq Ī“1 Ī“2 ==> asgn_eq Ī“1 Ī“2) r_emb
T, C: Type
CC: context T C
val: Famā‚ T C
VM: subst_monoid val
VML: subst_monoid_laws val
Ī“1, Ī“2: C

Proper (asgn_eq Ī“1 Ī“2 ==> asgn_eq Ī“1 Ī“2) r_emb
intros ?? H ??; cbn; now rewrite H. Qed.
T, C: Type
CC: context T C
val: Famā‚ T C
VM: subst_monoid val
VML: subst_monoid_laws val
Ī“1, Ī“2, Ī“3: C

Proper (asgn_eq Ī“1 Ī“2 ==> asgn_eq Ī“2 Ī“3 ==> asgn_eq Ī“1 Ī“3) a_ren_r
T, C: Type
CC: context T C
val: Famā‚ T C
VM: subst_monoid val
VML: subst_monoid_laws val
Ī“1, Ī“2, Ī“3: C

Proper (asgn_eq Ī“1 Ī“2 ==> asgn_eq Ī“2 Ī“3 ==> asgn_eq Ī“1 Ī“3) a_ren_r
intros ?? H1 ?? H2 ??; cbn; now rewrite H1, H2. Qed.
T, C: Type
CC: context T C
val: Famā‚ T C
VM: subst_monoid val
VML: subst_monoid_laws val
Ī“1, Ī“2, Ī“3: C
r: Ī“1 āŠ† Ī“2
a: Ī“2 =[ val ]> Ī“3

r_emb r āŠ› a ā‰”ā‚ r įµ£āŠ› a
T, C: Type
CC: context T C
val: Famā‚ T C
VM: subst_monoid val
VML: subst_monoid_laws val
Ī“1, Ī“2, Ī“3: C
r: Ī“1 āŠ† Ī“2
a: Ī“2 =[ val ]> Ī“3

r_emb r āŠ› a ā‰”ā‚ r įµ£āŠ› a
intros ??; cbn; now rewrite v_sub_var. Qed.
T, C: Type
CC: context T C
val: Famā‚ T C
VM: subst_monoid val
VML: subst_monoid_laws val
Ī“: C

r_emb r_id ā‰”ā‚ a_id
T, C: Type
CC: context T C
val: Famā‚ T C
VM: subst_monoid val
VML: subst_monoid_laws val
Ī“: C

r_emb r_id ā‰”ā‚ a_id
reflexivity. Qed.
T, C: Type
CC: context T C
val: Famā‚ T C
VM: subst_monoid val
VML: subst_monoid_laws val
Ī“1, Ī“2, Ī“3, Ī“4: C
a: Ī“1 =[ val ]> Ī“2
b: Ī“2 =[ val ]> Ī“3
r: Ī“3 āŠ† Ī“4

(a āŠ› b) āŠ›įµ£ r ā‰”ā‚ a āŠ› (b āŠ›įµ£ r)
T, C: Type
CC: context T C
val: Famā‚ T C
VM: subst_monoid val
VML: subst_monoid_laws val
Ī“1, Ī“2, Ī“3, Ī“4: C
a: Ī“1 =[ val ]> Ī“2
b: Ī“2 =[ val ]> Ī“3
r: Ī“3 āŠ† Ī“4

(a āŠ› b) āŠ›įµ£ r ā‰”ā‚ a āŠ› (b āŠ›įµ£ r)
intros ??; cbn; now rewrite <-v_sub_sub. Qed.
T, C: Type
CC: context T C
val: Famā‚ T C
VM: subst_monoid val
VML: subst_monoid_laws val
Ī“1, Ī“2, Ī“3, Ī“4: C
a: Ī“1 =[ val ]> Ī“2
r: Ī“2 āŠ† Ī“3
b: Ī“3 =[ val ]> Ī“4

(a āŠ›įµ£ r) āŠ› b ā‰”ā‚ a āŠ› (r įµ£āŠ› b)
T, C: Type
CC: context T C
val: Famā‚ T C
VM: subst_monoid val
VML: subst_monoid_laws val
Ī“1, Ī“2, Ī“3, Ī“4: C
a: Ī“1 =[ val ]> Ī“2
r: Ī“2 āŠ† Ī“3
b: Ī“3 =[ val ]> Ī“4

(a āŠ›įµ£ r) āŠ› b ā‰”ā‚ a āŠ› (r įµ£āŠ› b)
intros ??; cbn; now rewrite <-v_sub_sub, a_ren_r_simpl. Qed.
T, C: Type
CC: context T C
val: Famā‚ T C
VM: subst_monoid val
VML: subst_monoid_laws val
Ī“1, Ī“2, Ī“3, Ī“4: C
a: Ī“1 =[ val ]> Ī“2
b: Ī“2 =[ val ]> Ī“3
c: Ī“3 =[ val ]> Ī“4

(a āŠ› b) āŠ› c ā‰”ā‚ a āŠ› (b āŠ› c)
T, C: Type
CC: context T C
val: Famā‚ T C
VM: subst_monoid val
VML: subst_monoid_laws val
Ī“1, Ī“2, Ī“3, Ī“4: C
a: Ī“1 =[ val ]> Ī“2
b: Ī“2 =[ val ]> Ī“3
c: Ī“3 =[ val ]> Ī“4

(a āŠ› b) āŠ› c ā‰”ā‚ a āŠ› (b āŠ› c)
intros ??; cbn; now rewrite v_sub_sub. Qed.
T, C: Type
CC: context T C
val: Famā‚ T C
VM: subst_monoid val
VML: subst_monoid_laws val
Ī“1, Ī“2: C
a: Ī“1 =[ val ]> Ī“2

a āŠ› a_id ā‰”ā‚ a
T, C: Type
CC: context T C
val: Famā‚ T C
VM: subst_monoid val
VML: subst_monoid_laws val
Ī“1, Ī“2: C
a: Ī“1 =[ val ]> Ī“2

a āŠ› a_id ā‰”ā‚ a
intros ??; cbn; now rewrite v_var_sub. Qed.
T, C: Type
CC: context T C
val: Famā‚ T C
VM: subst_monoid val
VML: subst_monoid_laws val
Ī“1, Ī“2: C
a: Ī“1 =[ val ]> Ī“2

a_id āŠ› a ā‰”ā‚ a
T, C: Type
CC: context T C
val: Famā‚ T C
VM: subst_monoid val
VML: subst_monoid_laws val
Ī“1, Ī“2: C
a: Ī“1 =[ val ]> Ī“2

a_id āŠ› a ā‰”ā‚ a
T, C: Type
CC: context T C
val: Famā‚ T C
VM: subst_monoid val
VML: subst_monoid_laws val
Ī“1, Ī“2: C
a: Ī“1 =[ val ]> Ī“2
a0: T
a1: Ī“1 āˆ‹ a0

a_id a1 įµ„āŠ› a = a a0 a1
now rewrite v_sub_var. Qed. End properties.