@@ -115,51 +115,49 @@ def codeToSKINat : Code → SKI
115115
116116/-! ### Correctness proofs -/
117117
118+ /-- Helper for total functions: if `c.eval` is total with output `g n`, and `t` reduces
119+ to a Church numeral for `g n`, then `t` computes `c.eval`. -/
120+ private theorem computes_of_total (t : SKI) (c : Code) (g : ℕ → ℕ)
121+ (heval : ∀ n, c.eval n = Part.some (g n))
122+ (hcorrect : ∀ n cn, IsChurch n cn → IsChurch (g n) (t ⬝ cn)) :
123+ Computes t c.eval := by
124+ intro n cn hcn m hm; rw [heval] at hm; obtain rfl := Part.some_injective hm
125+ exact hcorrect n cn hcn
126+
118127/-- `Code.zero` computes the constant zero function. -/
119- theorem zero_computes : Computes (K ⬝ SKI.Zero) (Code.eval .zero) := by
120- intro n cn hcn m hm
121- have h0 : Code.eval .zero n = Part.some 0 := by
122- rw [show Code.zero = Code.const 0 from rfl, Code.eval_const]
123- rw [h0] at hm; obtain rfl := Part.some_injective hm
124- exact isChurch_trans 0 (MRed.K SKI.Zero cn) zero_correct
128+ theorem zero_computes : Computes (K ⬝ SKI.Zero) (Code.eval .zero) :=
129+ computes_of_total _ .zero (fun _ => 0 )
130+ (fun n => by rw [show Code.zero = Code.const 0 from rfl, Code.eval_const])
131+ (fun _ _ _ => isChurch_trans 0 (MRed.K SKI.Zero _) zero_correct)
125132
126133/-- `Code.succ` computes the successor function. -/
127- theorem succ_computes : Computes SKI.Succ (Code.eval .succ) := by
128- intro n cn hcn m hm
129- have h0 : Code.eval .succ n = Part.some (n + 1 ) := by
130- simp only [Code.eval, PFun.coe_val]
131- rw [h0] at hm; obtain rfl := Part.some_injective hm
132- exact succ_correct n cn hcn
134+ theorem succ_computes : Computes SKI.Succ (Code.eval .succ) :=
135+ computes_of_total _ .succ (· + 1 )
136+ (fun _ => by simp only [Code.eval, PFun.coe_val])
137+ (fun n cn hcn => succ_correct n cn hcn)
133138
134139/-- `Code.left` computes the left projection of `Nat.unpair`. -/
135- theorem left_computes : Computes NatUnpairLeft (Code.eval .left) := by
136- intro n cn hcn m hm
137- have h0 : Code.eval .left n = Part.some (Nat.unpair n).1 := by
138- simp only [Code.eval, PFun.coe_val]
139- rw [h0] at hm; obtain rfl := Part.some_injective hm
140- exact natUnpairLeft_correct n cn hcn
140+ theorem left_computes : Computes NatUnpairLeft (Code.eval .left) :=
141+ computes_of_total _ .left (fun n => (Nat.unpair n).1 )
142+ (fun _ => by simp only [Code.eval, PFun.coe_val])
143+ (fun n cn hcn => natUnpairLeft_correct n cn hcn)
141144
142145/-- `Code.right` computes the right projection of `Nat.unpair`. -/
143- theorem right_computes : Computes NatUnpairRight (Code.eval .right) := by
144- intro n cn hcn m hm
145- have h0 : Code.eval .right n = Part.some (Nat.unpair n).2 := by
146- simp only [Code.eval, PFun.coe_val]
147- rw [h0] at hm; obtain rfl := Part.some_injective hm
148- exact natUnpairRight_correct n cn hcn
146+ theorem right_computes : Computes NatUnpairRight (Code.eval .right) :=
147+ computes_of_total _ .right (fun n => (Nat.unpair n).2 )
148+ (fun _ => by simp only [Code.eval, PFun.coe_val])
149+ (fun n cn hcn => natUnpairRight_correct n cn hcn)
149150
150151/-- Composition of computable functions is computable. -/
151152theorem comp_computes {f g : ℕ →. ℕ} {tf tg : SKI}
152153 (hf : Computes tf f) (hg : Computes tg g) :
153154 Computes (B ⬝ tf ⬝ tg) (fun n => g n >>= f) := by
154155 intro n cn hcn m hm
155156 simp only at hm
156- have hm' : m ∈ (g n >>= f) := by rw [hm]; exact Part.mem_some m
157- obtain ⟨intermediate, hint_mem, hm_mem⟩ := Part.mem_bind_iff.mp hm'
158- have hgn : g n = Part.some intermediate := Part.eq_some_iff.mpr hint_mem
159- have hfint : f intermediate = Part.some m := Part.eq_some_iff.mpr hm_mem
160- have hcint := hg n cn hcn intermediate hgn
161- have hcm := hf intermediate (tg ⬝ cn) hcint m hfint
162- exact isChurch_trans _ (B_def tf tg cn) hcm
157+ obtain ⟨intermediate, hint_mem, hm_mem⟩ := Part.mem_bind_iff.mp (hm ▸ Part.mem_some m)
158+ have hcint := hg n cn hcn intermediate (Part.eq_some_iff.mpr hint_mem)
159+ exact isChurch_trans _ (B_def tf tg cn)
160+ (hf intermediate (tg ⬝ cn) hcint m (Part.eq_some_iff.mpr hm_mem))
163161
164162/-- Pairing of computable functions is computable. -/
165163theorem pair_computes {f g : ℕ →. ℕ} {tf tg : SKI}
@@ -168,24 +166,13 @@ theorem pair_computes {f g : ℕ →. ℕ} {tf tg : SKI}
168166 (fun n => Nat.pair <$> f n <*> g n) := by
169167 intro n cn hcn m hm
170168 simp only at hm
171- -- hm : Nat.pair <$> f n <*> g n = Part.some m
172- have hm' : m ∈ (Nat.pair <$> f n <*> g n) := by rw [hm]; exact Part.mem_some m
173- -- Unfold <*> into bind: pf <*> pa = pf >>= fun h => h <$> pa
174- have hm_bind : m ∈ Part.bind (Part.map Nat.pair (f n)) (fun h => Part.map h (g n)) := hm'
175- obtain ⟨h, hh_mem, hm_in_h⟩ := Part.mem_bind_iff.mp hm_bind
176- obtain ⟨a, ha_mem, hh_eq⟩ := (Part.mem_map_iff _).mp hh_mem
177- subst hh_eq
178- obtain ⟨b, hb_mem, hm_eq⟩ := (Part.mem_map_iff _).mp hm_in_h
179- have hfn : f n = Part.some a := Part.eq_some_iff.mpr ha_mem
180- have hgn : g n = Part.some b := Part.eq_some_iff.mpr hb_mem
181- have hca := hf n cn hcn a hfn
182- have hcb := hg n cn hcn b hgn
183- subst hm_eq
184- have hred : (S ⬝ (B ⬝ NatPair ⬝ tf) ⬝ tg ⬝ cn) ↠
185- (NatPair ⬝ (tf ⬝ cn) ⬝ (tg ⬝ cn)) := calc
186- _ ↠ (B ⬝ NatPair ⬝ tf) ⬝ cn ⬝ (tg ⬝ cn) := MRed.S _ _ _
187- _ ↠ NatPair ⬝ (tf ⬝ cn) ⬝ (tg ⬝ cn) := MRed.head _ (B_def _ _ _)
188- exact isChurch_trans _ hred (natPair_correct a b _ _ hca hcb)
169+ obtain ⟨h, hh_mem, hm_in_h⟩ := Part.mem_bind_iff.mp (hm ▸ Part.mem_some m)
170+ obtain ⟨a, ha_mem, rfl⟩ := (Part.mem_map_iff _).mp hh_mem
171+ obtain ⟨b, hb_mem, rfl⟩ := (Part.mem_map_iff _).mp hm_in_h
172+ have hca := hf n cn hcn a (Part.eq_some_iff.mpr ha_mem)
173+ have hcb := hg n cn hcn b (Part.eq_some_iff.mpr hb_mem)
174+ exact isChurch_trans _ ((MRed.S _ _ _).trans (MRed.head _ (B_def _ _ _)))
175+ (natPair_correct a b _ _ hca hcb)
189176
190177/-- Helper: `Rec` correctly implements primitive recursion from `Code.prec`. -/
191178private theorem prec_rec_correct (f g : Code) (tf tg : SKI)
@@ -257,36 +244,30 @@ private theorem rfindAbove_induction (f : Code) (tf : SKI)
257244 (∀ i < n, ∃ vi, vi ≠ 0 ∧
258245 f.eval (Nat.pair a₀ (m + i)) = Part.some vi) →
259246 IsChurch (m + n) (RFindAbove ⬝ x ⬝ g) := by
247+ subst hg
248+ -- Helper: `B ⬝ tf ⬝ (NatPair ⬝ ca) ⬝ x` computes `f.eval (Nat.pair a₀ m)`.
249+ have hgx : ∀ m x, IsChurch m x → ∀ v, f.eval (Nat.pair a₀ m) = Part.some v →
250+ IsChurch v (B ⬝ tf ⬝ (NatPair ⬝ ca) ⬝ x) := fun m x hx v hv =>
251+ isChurch_trans _ (B_def tf (NatPair ⬝ ca) x)
252+ (ihf _ _ (natPair_correct a₀ m ca x hca hx) v hv)
260253 intro n
261254 induction n with
262255 | zero =>
263256 intro m x hx hroot _
264257 simp only [Nat.add_zero] at hroot ⊢
265- apply isChurch_trans (a' := RFindAboveAux ⬝ RFindAbove ⬝ x ⬝ g)
266- · apply MRed.head; apply MRed.head; exact fixedPoint_correct _
258+ apply isChurch_trans _ (RFindAbove_unfold x _)
267259 apply isChurch_trans (a' := x)
268- · apply rfindAboveAux_base
269- -- Need: IsChurch 0 (g ⬝ x)
270- subst hg
271- apply isChurch_trans _ (B_def tf (NatPair ⬝ ca) x)
272- have hpair := natPair_correct a₀ m ca x hca hx
273- exact ihf _ _ hpair 0 hroot
260+ · exact rfindAboveAux_base _ _ _ (hgx m x hx 0 hroot)
274261 · exact hx
275262 | succ n ih =>
276263 intro m x hx hroot hbelow
277- apply isChurch_trans (a' := RFindAboveAux ⬝ RFindAbove ⬝ x ⬝ g)
278- · apply MRed.head; apply MRed.head; exact fixedPoint_correct _
279- -- f at m is nonzero, so step
264+ apply isChurch_trans _ (RFindAbove_unfold x _)
280265 obtain ⟨v₀, hv₀_ne, hv₀_eval⟩ := hbelow 0 (by omega)
281266 simp only [Nat.add_zero] at hv₀_eval
282- apply isChurch_trans (a' := RFindAbove ⬝ (SKI.Succ ⬝ x) ⬝ g )
267+ apply isChurch_trans (a' := RFindAbove ⬝ (SKI.Succ ⬝ x) ⬝ _ )
283268 · apply rfindAboveAux_step (m := v₀ - 1 )
284- subst hg
285- apply isChurch_trans _ (B_def tf (NatPair ⬝ ca) x)
286- have hpair := natPair_correct a₀ m ca x hca hx
287- have hv₀_pos : v₀ - 1 + 1 = v₀ := Nat.succ_pred_eq_of_ne_zero hv₀_ne
288- rw [hv₀_pos]
289- exact ihf _ _ hpair v₀ hv₀_eval
269+ have : v₀ - 1 + 1 = v₀ := Nat.succ_pred_eq_of_ne_zero hv₀_ne
270+ rw [this]; exact hgx m x hx v₀ hv₀_eval
290271 · have h := ih (m + 1 ) (SKI.Succ ⬝ x) (succ_correct m x hx)
291272 (by rw [show m + 1 + n = m + (n + 1 ) from by omega]; exact hroot)
292273 (by
0 commit comments