@@ -8,16 +8,17 @@ module -- shake: keep-downstream
88
99public import Cslib.Init
1010public import Mathlib.Analysis.Normed.Field.Lemmas
11+ meta import Lean.Elab.ConfigEval
1112import Qq
1213
1314/-! Computable chacterization of infinite types. -/
1415
16+ namespace Cslib
17+
1518@[expose] public section
1619
1720universe u
1821
19- namespace Cslib
20-
2122/-- A type `α` has a computable `fresh` function if it is always possible, for any finite set
2223of `α`, to compute a fresh element not in the set. -/
2324class HasFresh (α : Type u) where
@@ -33,6 +34,63 @@ in proofs. -/
3334theorem HasFresh.fresh_exists {α : Type u} [HasFresh α] (s : Finset α) : ∃ a, a ∉ s :=
3435 ⟨fresh s, fresh_notMem s⟩
3536
37+ export HasFresh (fresh fresh_notMem fresh_exists)
38+
39+ /-- `HasFresh α` implies a computably infinite type. -/
40+ instance HasFresh.to_infinite (α : Type u) [HasFresh α] : Infinite α := by
41+ apply Infinite.of_not_fintype
42+ rintro ⟨elems, _⟩
43+ grind [fresh_notMem elems]
44+
45+ /-- All infinite types have an associated (at least noncomputable) fresh function.
46+ This, in conjunction with `HasFresh.to_infinite`, characterizes `HasFresh`. -/
47+ noncomputable instance (α : Type u) [Infinite α] : HasFresh α where
48+ fresh s := Infinite.exists_notMem_finset s |>.choose
49+ fresh_notMem s := by grind
50+
51+ open Finset in
52+ /-- Construct a fresh element from an embedding of `ℕ` using `Nat.find`. -/
53+ @[implicit_reducible]
54+ def HasFresh.ofNatEmbed {α : Type u} [DecidableEq α] (e : ℕ ↪ α) : HasFresh α where
55+ fresh s := e (Nat.find (p := fun n ↦ e n ∉ s) ⟨(s.preimage e e.2 .injOn).max.succ,
56+ fun h ↦ not_lt_of_ge (le_max <| mem_preimage.2 h) (WithBot.lt_succ _)⟩)
57+ fresh_notMem s := Nat.find_spec (p := fun n ↦ e n ∉ s) _
58+
59+ /-- Construct a fresh element given a function `f` with `x < f x`. -/
60+ @[implicit_reducible]
61+ def HasFresh.ofSucc {α : Type u} [Inhabited α] [SemilatticeSup α] (f : α → α) (hf : ∀ x, x < f x) :
62+ HasFresh α where
63+ fresh s := if hs : s.Nonempty then f (s.sup' hs id) else default
64+ fresh_notMem s h := if hs : s.Nonempty
65+ then not_le_of_gt (hf (s.sup' hs id)) <| by rw [dif_pos hs] at h; exact s.le_sup' id h
66+ else hs ⟨_, h⟩
67+
68+ /-- `ℕ` has a computable fresh function. -/
69+ instance : HasFresh ℕ :=
70+ .ofSucc (· + 1 ) Nat.lt_add_one
71+
72+ /-- `ℤ` has a computable fresh function. -/
73+ instance : HasFresh ℤ :=
74+ .ofSucc (· + 1 ) Int.lt_succ
75+
76+ /-- `ℚ` has a computable fresh function. -/
77+ instance : HasFresh ℚ :=
78+ .ofSucc (· + 1 ) fun x ↦ lt_add_of_pos_right x one_pos
79+
80+ /-- If `α` has a computable fresh function, then so does `Finset α`. -/
81+ instance {α : Type u} [DecidableEq α] [HasFresh α] : HasFresh (Finset α) :=
82+ .ofSucc (fun s ↦ insert (fresh s) s) fun s ↦ Finset.ssubset_insert <| fresh_notMem s
83+
84+ /-- If `α` is inhabited, then `Multiset α` has a computable fresh function. -/
85+ instance {α : Type u} [DecidableEq α] [Inhabited α] : HasFresh (Multiset α) :=
86+ .ofSucc (fun s ↦ default ::ₘ s) fun _ ↦ Multiset.lt_cons_self _ _
87+
88+ /-- `ℕ → ℕ` has a computable fresh function. -/
89+ instance : HasFresh (ℕ → ℕ) :=
90+ .ofSucc (fun f x ↦ f x + 1 ) fun _ ↦ Pi.lt_def.2 ⟨fun _ ↦ Nat.le_succ _, 0 , Nat.lt_succ_self _⟩
91+
92+ end
93+
3694public meta section
3795
3896open Lean Elab Term Meta Parser Tactic
@@ -45,7 +103,7 @@ structure FreeUnionConfig where
45103 finset : Bool := true
46104
47105/-- Elaborate a FreeUnionConfig. -/
48- declare_config_elab elabFreeUnionConfig FreeUnionConfig
106+ declare_term_config_elab elabFreeUnionConfig FreeUnionConfig
49107
50108/--
51109 Given a `DecidableEq Var` instance, this elaborator automatically constructs
@@ -87,7 +145,7 @@ set_option linter.style.emptyLine false in
87145def HasFresh.freeUnion : TermElab := fun stx _ => do
88146 match stx with
89147 | `(free_union $cfg $[[$maps,*]]? $var:term) =>
90- let cfg ← elabFreeUnionConfig cfg |>.run { elaborator := .anonymous } |>.run' { goals := [] }
148+ let cfg ← elabFreeUnionConfig cfg
91149
92150 -- the type of our variables
93151 let var ← elabType var
@@ -124,59 +182,4 @@ def HasFresh.freeUnion : TermElab := fun stx _ => do
124182
125183end
126184
127- export HasFresh (fresh fresh_notMem fresh_exists)
128-
129- /-- `HasFresh α` implies a computably infinite type. -/
130- instance HasFresh.to_infinite (α : Type u) [HasFresh α] : Infinite α := by
131- apply Infinite.of_not_fintype
132- rintro ⟨elems, _⟩
133- grind [fresh_notMem elems]
134-
135- /-- All infinite types have an associated (at least noncomputable) fresh function.
136- This, in conjunction with `HasFresh.to_infinite`, characterizes `HasFresh`. -/
137- noncomputable instance (α : Type u) [Infinite α] : HasFresh α where
138- fresh s := Infinite.exists_notMem_finset s |>.choose
139- fresh_notMem s := by grind
140-
141- open Finset in
142- /-- Construct a fresh element from an embedding of `ℕ` using `Nat.find`. -/
143- @[implicit_reducible]
144- def HasFresh.ofNatEmbed {α : Type u} [DecidableEq α] (e : ℕ ↪ α) : HasFresh α where
145- fresh s := e (Nat.find (p := fun n ↦ e n ∉ s) ⟨(s.preimage e e.2 .injOn).max.succ,
146- fun h ↦ not_lt_of_ge (le_max <| mem_preimage.2 h) (WithBot.lt_succ _)⟩)
147- fresh_notMem s := Nat.find_spec (p := fun n ↦ e n ∉ s) _
148-
149- /-- Construct a fresh element given a function `f` with `x < f x`. -/
150- @[implicit_reducible]
151- def HasFresh.ofSucc {α : Type u} [Inhabited α] [SemilatticeSup α] (f : α → α) (hf : ∀ x, x < f x) :
152- HasFresh α where
153- fresh s := if hs : s.Nonempty then f (s.sup' hs id) else default
154- fresh_notMem s h := if hs : s.Nonempty
155- then not_le_of_gt (hf (s.sup' hs id)) <| by rw [dif_pos hs] at h; exact s.le_sup' id h
156- else hs ⟨_, h⟩
157-
158- /-- `ℕ` has a computable fresh function. -/
159- instance : HasFresh ℕ :=
160- .ofSucc (· + 1 ) Nat.lt_add_one
161-
162- /-- `ℤ` has a computable fresh function. -/
163- instance : HasFresh ℤ :=
164- .ofSucc (· + 1 ) Int.lt_succ
165-
166- /-- `ℚ` has a computable fresh function. -/
167- instance : HasFresh ℚ :=
168- .ofSucc (· + 1 ) fun x ↦ lt_add_of_pos_right x one_pos
169-
170- /-- If `α` has a computable fresh function, then so does `Finset α`. -/
171- instance {α : Type u} [DecidableEq α] [HasFresh α] : HasFresh (Finset α) :=
172- .ofSucc (fun s ↦ insert (fresh s) s) fun s ↦ Finset.ssubset_insert <| fresh_notMem s
173-
174- /-- If `α` is inhabited, then `Multiset α` has a computable fresh function. -/
175- instance {α : Type u} [DecidableEq α] [Inhabited α] : HasFresh (Multiset α) :=
176- .ofSucc (fun s ↦ default ::ₘ s) fun _ ↦ Multiset.lt_cons_self _ _
177-
178- /-- `ℕ → ℕ` has a computable fresh function. -/
179- instance : HasFresh (ℕ → ℕ) :=
180- .ofSucc (fun f x ↦ f x + 1 ) fun _ ↦ Pi.lt_def.2 ⟨fun _ ↦ Nat.le_succ _, 0 , Nat.lt_succ_self _⟩
181-
182185end Cslib
0 commit comments