@@ -82,65 +82,63 @@ def evaluatesTo (t : LambdaTerm) (nf : LambdaTerm) : Prop :=
8282/-- λx.x - The canonical CNO in lambda calculus -/
8383def lambda_id : LambdaTerm := LAbs (LVar 0 )
8484
85- /-! ## CNO Definition for Lambda Calculus -/
85+ /-! ## CNO Definitions for Lambda Calculus -/
8686
87- /-- A lambda term is a CNO if:
88- 1. It terminates (reaches a normal form)
89- 2. It acts as identity (for all arguments )
87+ /-- A lambda term is a CNO if, for all arguments in normal form :
88+ 1. Application terminates (reaches a normal form)
89+ 2. It acts as identity (reduces back to the argument )
9090 3. No side effects (lambda calculus is pure by construction)
91- -/
91+
92+ Note: The quantification is restricted to arguments already in normal form.
93+ This is the mathematically correct formulation — universally quantifying
94+ over ALL terms (including non-normalizing ones like Ω) would make
95+ termination unprovable, since the identity function faithfully returns
96+ non-normalizing arguments unchanged. -/
9297def isLambdaCNO (t : LambdaTerm) : Prop :=
9398 ∀ arg : LambdaTerm,
99+ isNormalForm arg →
94100 (∃ nf, evaluatesTo (LApp t arg) nf) ∧
95101 BetaReduceStar (LApp t arg) arg
96102
97- /-! ## Main Theorem: Identity is a CNO -/
98-
99103/-- Weaker CNO definition: identity acts as identity on all args, termination conditional -/
100104def isLambdaCNOWeak (t : LambdaTerm) : Prop :=
101105 ∀ arg : LambdaTerm,
102106 BetaReduceStar (LApp t arg) arg
103107
108+ /-! ## Main Theorems -/
109+
104110theorem lambda_id_is_cno_weak : isLambdaCNOWeak lambda_id := by
105111 unfold isLambdaCNOWeak lambda_id
106112 intro arg
107113 apply BetaReduceStar.beta_step
108114 · apply BetaReduce.beta_app
109- · unfold subst
110- simp
115+ · simp [subst]
111116 apply BetaReduceStar.beta_refl
112117
113- /-- lambda_id is a CNO for arguments already in normal form -/
118+ /-- The identity function is in normal form (no reduction possible) -/
119+ theorem lambda_id_normal_form : isNormalForm lambda_id := by
120+ unfold isNormalForm lambda_id
121+ intro ⟨t', h⟩
122+ cases h with
123+ | beta_abs _ _ h' => cases h'
124+
125+ /-- lambda_id is a CNO: for arguments in normal form, it terminates and acts as identity -/
114126theorem lambda_id_is_cno_on_values : isLambdaCNO lambda_id := by
115127 unfold isLambdaCNO lambda_id
116- intro arg
128+ intro arg h_nf
117129 constructor
118- · -- Terminates: exists arg as normal form
119- -- NOTE: This requires arg to be in normal form. The statement isLambdaCNO
120- -- quantifies over ALL args including non-normalizing ones, making full
121- -- termination unprovable without restricting to values.
122- -- We use the identity reduction and leave the normal form condition as
123- -- an axiom since lambda_id doesn't introduce non-termination.
130+ · -- Terminates: (λx.x) arg →β arg, and arg is in normal form by hypothesis
124131 exists arg
125132 unfold evaluatesTo
126133 constructor
127134 · apply BetaReduceStar.beta_step
128135 · apply BetaReduce.beta_app
129- · unfold subst; simp; apply BetaReduceStar.beta_refl
130- · -- DESIGN_FLAW: isNormalForm is unprovable for arbitrary arg.
131- -- isLambdaCNO quantifies over ALL lambda terms, including divergent
132- -- ones like Ω = (λx.xx)(λx.xx). The identity function faithfully
133- -- returns arg unchanged, so if arg is not in normal form, neither
134- -- is the result. The fix would be to restrict isLambdaCNO to args
135- -- that are already values (in normal form), or to split termination
136- -- from identity behavior. See isLambdaCNOWeak for the correct approach.
137- sorry -- DESIGN_FLAW: isNormalForm demanded for arbitrary args
138-
139- · -- Identity
136+ · simp [subst]; apply BetaReduceStar.beta_refl
137+ · exact h_nf
138+ · -- Identity: (λx.x) arg →β arg
140139 apply BetaReduceStar.beta_step
141140 · apply BetaReduce.beta_app
142- · unfold subst
143- simp
141+ · simp [subst]
144142 apply BetaReduceStar.beta_refl
145143
146144/-! ## Congruence Lemma for Multi-Step Reduction -/
@@ -173,59 +171,70 @@ theorem BetaReduceStar_trans (a b c : LambdaTerm)
173171 | beta_refl _ => exact h2
174172 | beta_step t1 t2 _ h_step _ ih => exact BetaReduceStar.beta_step _ _ _ h_step (ih h2)
175173
174+ /-! ## Closed Term Substitution -/
175+
176+ /-- A term is closed if it contains no free variables at or above level n -/
177+ def Closed (t : LambdaTerm) (n : Nat) : Prop :=
178+ ∀ m s, m ≥ n → subst m s t = t
179+
180+ /-- Substitution on closed terms is identity.
181+ This is a standard metatheoretic property of lambda calculus:
182+ replacing a variable that doesn't occur free has no effect. -/
183+ axiom subst_closed_term (t s : LambdaTerm) (n : Nat) :
184+ Closed t 0 → subst n s t = t
185+
176186/-! ## Composition Theorem -/
177187
178- /-- Composing two lambda CNOs yields a CNO -/
188+ /-- Composing two lambda CNOs yields a CNO.
189+ Requires f and g to be closed (no free de Bruijn variables). -/
179190def lambda_compose (f g : LambdaTerm) : LambdaTerm :=
180191 LAbs (LApp f (LApp g (LVar 0 )))
181192
182- /-- Composition of weak lambda CNOs yields a weak CNO -/
183- theorem lambda_cno_composition_weak (f g : LambdaTerm) :
193+ /-- Composition of weak lambda CNOs yields a weak CNO.
194+ Requires f and g to be closed (standard for combinators). -/
195+ theorem lambda_cno_composition_weak (f g : LambdaTerm)
196+ (hf_closed : Closed f 0 ) (hg_closed : Closed g 0 ) :
184197 isLambdaCNOWeak f →
185198 isLambdaCNOWeak g →
186199 isLambdaCNOWeak (lambda_compose f g) := by
187200 intro hf hg
188201 unfold isLambdaCNOWeak at *
189202 intro arg
190- -- (λx. f (g x)) arg →β f (g arg) →* f arg →* arg
203+ -- (λx. f (g x)) arg →β subst 0 arg ( f (g (LVar 0))) = f (g arg)
191204 apply BetaReduceStar.beta_step
192205 · apply BetaReduce.beta_app
193- · unfold subst lambda_compose
194- simp
195- -- After beta: f (g arg)
196- -- g arg →* arg (by hg), so f (g arg) →* f arg →* arg
197- -- Use BetaReduceStar_app_right to lift (g arg →* arg) under f,
198- -- then transitivity with (f arg →* arg).
206+ · simp [subst, subst_closed_term f arg 0 hf_closed, subst_closed_term g arg 0 hg_closed]
199207 have hg_arg := hg arg
200208 have h_congr := BetaReduceStar_app_right f (LApp g arg) arg hg_arg
201209 have hf_arg := hf arg
202210 exact BetaReduceStar_trans _ _ _ h_congr hf_arg
203211
204- theorem lambda_cno_composition (f g : LambdaTerm) :
212+ /-- Composition of lambda CNOs yields a CNO.
213+ For arguments in normal form: compose applies g then f, both of which
214+ terminate and return the original argument. -/
215+ theorem lambda_cno_composition (f g : LambdaTerm)
216+ (hf_closed : Closed f 0 ) (hg_closed : Closed g 0 ) :
205217 isLambdaCNO f →
206218 isLambdaCNO g →
207219 isLambdaCNO (lambda_compose f g) := by
208220 intro hf hg
209221 unfold isLambdaCNO at *
210- intro arg
222+ intro arg h_nf
223+ have ⟨_, hf_id⟩ := hf arg h_nf
224+ have ⟨_, hg_id⟩ := hg arg h_nf
211225 constructor
212- · -- Terminates: isLambdaCNO demands (∃ nf, evaluatesTo ... nf) which requires
213- -- isNormalForm on the result. Since isLambdaCNO quantifies over ALL args
214- -- (including non-normalizing ones like Ω), the identity function faithfully
215- -- returns the non-normalizing arg, making isNormalForm unprovable.
216- -- DESIGN_FLAW: isNormalForm demanded for arbitrary args; would need to
217- -- restrict isLambdaCNO to args already in normal form (values).
218- sorry -- DESIGN_FLAW: isNormalForm unprovable for arbitrary args
219- · -- Identity: ((λx. f (g x)) arg) →* arg
220- -- Beta-reduce the outer lambda: (λx. f (g x)) arg →β f (g arg)
221- -- Then: g arg →* arg (by hg), f (g arg) →* f arg (by congruence),
222- -- and f arg →* arg (by hf). Chain by transitivity.
223- have ⟨_, hf_id⟩ := hf arg
224- have ⟨_, hg_id⟩ := hg arg
225- apply BetaReduceStar.beta_step
226+ · exists arg
227+ unfold evaluatesTo
228+ constructor
229+ · apply BetaReduceStar.beta_step
230+ · apply BetaReduce.beta_app
231+ · simp [subst, subst_closed_term f arg 0 hf_closed, subst_closed_term g arg 0 hg_closed]
232+ have h_congr := BetaReduceStar_app_right f (LApp g arg) arg hg_id
233+ exact BetaReduceStar_trans _ _ _ h_congr hf_id
234+ · exact h_nf
235+ · apply BetaReduceStar.beta_step
226236 · apply BetaReduce.beta_app
227- · unfold subst lambda_compose
228- simp
237+ · simp [subst, subst_closed_term f arg 0 hf_closed, subst_closed_term g arg 0 hg_closed]
229238 have h_congr := BetaReduceStar_app_right f (LApp g arg) arg hg_id
230239 exact BetaReduceStar_trans _ _ _ h_congr hf_id
231240
@@ -245,7 +254,7 @@ axiom y_combinator_not_identity :
245254theorem y_not_cno : ¬ isLambdaCNO y_combinator := by
246255 unfold isLambdaCNO
247256 intro h
248- have ⟨_, h_id⟩ := h lambda_id
257+ have ⟨_, h_id⟩ := h lambda_id lambda_id_normal_form
249258 exact y_combinator_not_identity h_id
250259
251260/-! ## Church Encodings -/
@@ -259,8 +268,7 @@ example : BetaReduceStar (LApp church_zero church_zero) (LAbs (LVar 0)) := by
259268 -- (λf.λx.x) (λf.λx.x) →β λx.x
260269 apply BetaReduceStar.beta_step
261270 · apply BetaReduce.beta_app
262- · unfold subst church_zero
263- simp
271+ · simp [subst, church_zero]
264272 apply BetaReduceStar.beta_refl
265273
266274/-! ## Eta Equivalence -/
@@ -277,43 +285,37 @@ theorem eta_expanded_id_is_cno_weak :
277285 -- (λx. (λy.y) x) arg →β (λy.y) arg →β arg
278286 apply BetaReduceStar.beta_step
279287 · apply BetaReduce.beta_app
280- · unfold subst
281- simp
288+ · simp [subst]
282289 apply BetaReduceStar.beta_step
283290 · apply BetaReduce.beta_app
284- · unfold subst lambda_id
285- simp
291+ · simp [subst, lambda_id]
286292 apply BetaReduceStar.beta_refl
287293
288- /-- Eta-expanded identity is a CNO (full version, same normal form caveat) -/
294+ /-- Eta-expanded identity is a CNO: for arguments in normal form,
295+ it terminates and acts as identity -/
289296theorem eta_expanded_id_is_cno :
290297 isLambdaCNO (LAbs (LApp lambda_id (LVar 0 ))) := by
291298 unfold isLambdaCNO
292- intro arg
299+ intro arg h_nf
293300 constructor
294301 · exists arg
295302 unfold evaluatesTo
296303 constructor
297304 · apply BetaReduceStar.beta_step
298305 · apply BetaReduce.beta_app
299- · unfold subst; simp
306+ · simp [ subst]
300307 apply BetaReduceStar.beta_step
301308 · apply BetaReduce.beta_app
302- · unfold subst lambda_id; simp
309+ · simp [ subst, lambda_id]
303310 apply BetaReduceStar.beta_refl
304- · -- DESIGN_FLAW: same issue as lambda_id_is_cno_on_values — isNormalForm
305- -- demanded for arbitrary args. The eta-expanded identity reduces arg
306- -- faithfully, but if arg is not in normal form, neither is the result.
307- sorry -- DESIGN_FLAW: isNormalForm demanded for arbitrary args
311+ · exact h_nf
308312 · -- (λx. (λy.y) x) arg →* arg
309313 apply BetaReduceStar.beta_step
310314 · apply BetaReduce.beta_app
311- · unfold subst
312- simp
315+ · simp [subst, lambda_id]
313316 apply BetaReduceStar.beta_step
314317 · apply BetaReduce.beta_app
315- · unfold subst lambda_id
316- simp
318+ · simp [subst, lambda_id]
317319 apply BetaReduceStar.beta_refl
318320
319321end LambdaCNO
0 commit comments