@@ -17,43 +17,96 @@ Contexts as pairs of free variables and types.
1717
1818universe u v
1919
20- variable {Var : Type u} {Ty : Type v} [DecidableEq Var]
20+ variable {α : Type u} {β : Type v}
21+
22+ -- TODO: These are pieces of API that cannot be directly automated by adding `grind` attributes to
23+ -- `Mathlib.Data.List.Sigma`. We should consider upstreaming them to Mathlib.
24+ namespace List
25+
26+ variable {β : α → Type v} {l₁ l₂ : List (Sigma β)}
27+
28+ /-- Keys distribute with appending. -/
29+ theorem keys_append : (l₁ ++ l₂).keys = l₁.keys ++ l₂.keys := by
30+ simp [keys]
31+
32+ variable [DecidableEq α] in
33+ /-- Sublists without duplicate keys preserve lookups. -/
34+ theorem sublist_dlookup (nd₂ : l₂.NodupKeys) (s : l₁ <+ l₂) (mem : b ∈ l₁.dlookup a) :
35+ b ∈ l₂.dlookup a := by
36+ grind [Option.mem_def, → perm_nodupKeys, dlookup_append, => perm_dlookup,
37+ → Sublist.exists_perm_append]
38+
39+ @[grind =]
40+ lemma nodupKeys_middle : (l₁ ++ s :: l₂).NodupKeys ↔ (s :: (l₁ ++ l₂)).NodupKeys := by
41+ simp_all [NodupKeys, keys, nodup_middle]
42+
43+ end List
2144
2245namespace LambdaCalculus.LocallyNameless
2346
47+ variable [DecidableEq α]
48+
2449/-- A typing context is a list of free variables and corresponding types. -/
25- abbrev Context (Var : Type u) (Ty : Type v) := List ((_ : Var ) × Ty )
50+ abbrev Context (α : Type u) (β : Type v) := List ((_ : α ) × β )
2651
2752namespace Context
2853
2954open List
3055
31- /-- The domain of a context is the finite set of free variables it uses. -/
32- @[simp, grind =]
33- def dom : Context Var Ty → Finset Var := toFinset ∘ keys
56+ -- we would like grind to see through certain notations
57+ attribute [scoped grind =] Option.mem_def
58+ attribute [scoped grind _=_] List.append_eq
59+ attribute [scoped grind =] List.Nodup
60+ attribute [scoped grind =] List.NodupKeys
61+ attribute [scoped grind _=_] List.singleton_append
3462
35- /-- A well-formed context. -/
36- abbrev Ok : Context Var Ty → Prop := NodupKeys
63+ -- a few grinds on Option:
64+ attribute [scoped grind =] Option.or_eq_some_iff
65+ attribute [scoped grind =] Option.or_eq_none_iff
3766
38- instance : HasWellFormed (Context Var Ty) :=
39- ⟨Ok⟩
67+ -- we would like grind to treat list and finset membership the same
68+ attribute [scoped grind _=_] List.mem_toFinset
4069
41- variable {Γ Δ : Context Var Ty}
70+ -- otherwise, we mostly reuse existing API in `Mathlib.Data.List.Sigma`
71+ attribute [scoped grind =] List.keys_cons
72+ attribute [scoped grind =] List.dlookup_cons_eq
73+ attribute [scoped grind =] List.dlookup_cons_ne
74+ attribute [scoped grind =] List.dlookup_nil
75+ attribute [scoped grind _=_] List.dlookup_isSome
76+ attribute [scoped grind →] List.perm_nodupKeys
4277
43- /-- Context membership is preserved on permuting a context. -/
44- theorem dom_perm_mem_iff (h : Γ.Perm Δ) {x : Var} : x ∈ Γ.dom ↔ x ∈ Δ.dom := by
45- induction h <;> simp_all only [dom, Function.comp_apply, mem_toFinset, keys_cons, mem_cons]
46- grind
78+ /-- The domain of a context is the finite set of free variables it uses. -/
79+ @[simp, grind =]
80+ def dom (Γ : Context α β) : Finset α := Γ.keys.toFinset
4781
48- omit [DecidableEq Var] in
49- /-- Context well-formedness is preserved on permuting a context. -/
50- @[scoped grind →]
51- theorem wf_perm (h : Γ.Perm Δ) : Γ✓ → Δ✓ := (List.perm_nodupKeys h).mp
82+ instance : HasWellFormed (Context α β) :=
83+ ⟨NodupKeys⟩
84+
85+ omit [DecidableEq α] in
86+ @[scoped grind _=_]
87+ theorem haswellformed_def (Γ : Context α β) : Γ✓ = Γ.NodupKeys := by rfl
88+
89+ variable {Γ Δ : Context α β}
5290
53- omit [DecidableEq Var ] in
91+ omit [DecidableEq α ] in
5492/-- Context well-formedness is preserved on removing an element. -/
5593@[scoped grind →]
5694theorem wf_strengthen (ok : (Δ ++ ⟨x, σ⟩ :: Γ)✓) : (Δ ++ Γ)✓ := by
57- exact List.NodupKeys.sublist (by simp) ok
95+ grind [keys_append]
96+
97+ /-- A mapping of values within a context. -/
98+ @[simp, scoped grind]
99+ def map_val (f : β → β) (Γ : Context α β) : Context α β :=
100+ Γ.map (fun ⟨var,ty⟩ => ⟨var,f ty⟩)
101+
102+ omit [DecidableEq α] in
103+ /-- A mapping of values preserves keys. -/
104+ @[scoped grind]
105+ lemma map_val_keys (f) : Γ.keys = (Γ.map_val f).keys := by
106+ induction Γ <;> grind
107+
108+ /-- A mapping of values maps lookups. -/
109+ lemma map_val_mem (mem : σ ∈ Γ.dlookup x) (f) : f σ ∈ (Γ.map_val f).dlookup x := by
110+ induction Γ <;> grind
58111
59112end LambdaCalculus.LocallyNameless.Context
0 commit comments