Skip to content

Commit 874776d

Browse files
Reorgnaize TPE helper lemmas
1 parent f96fe7c commit 874776d

File tree

8 files changed

+203
-235
lines changed

8 files changed

+203
-235
lines changed

cedar-lean/Cedar/Thm/Data/Control.lean

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -87,13 +87,10 @@ public theorem to_option_some {v : α} {res: Except ε α} :
8787
simp only [Except.toOption, h]
8888

8989
public theorem to_option_none {res: Except ε α} :
90-
res.toOption = .none (∃ err, res = .error err)
90+
res.toOption = .none (∃ err, res = .error err)
9191
:= by
92-
intro h
93-
simp [Except.toOption] at h
94-
split at h <;> simp at h
95-
rename_i err
96-
exists err
92+
simp only [Except.toOption]
93+
split <;> simp
9794

9895
public theorem to_option_left_ok {α ε₁ ε₂} {v : α} {res₁ : Except ε₁ α} {res₂ : Except ε₂ α} :
9996
res₁.toOption = res₂.toOption → res₁ = .ok v → res₂ = .ok v
@@ -150,3 +147,53 @@ public theorem do_error_to_option {res : Except ε α} {e : ε} :
150147
(do let (_ : α) ← res ; (.error e : Except ε α)).toOption = .none
151148
:= by
152149
cases res <;> simp [Except.toOption]
150+
151+
public theorem do_to_option_none {ε α β} {res : Except ε α} {f : α → Except ε β} :
152+
res.toOption = none → (do let x ← res; f x).toOption = none
153+
:= by
154+
intro h
155+
replace ⟨_, h⟩ := to_option_none.mp h
156+
simp [h, Except.toOption]
157+
158+
public theorem do_to_option_some {ε α β} {res : Except ε α} {v : α} {f : α → Except ε β} :
159+
res.toOption = .some v → (do let x ← res; f x) = f v
160+
:= by
161+
intro h
162+
simp [to_option_some.mp h]
163+
164+
public theorem to_option_eq_do₁ {α β ε} {res₁ res₂: Except ε α} (f : α → Except ε β) :
165+
res₁.toOption = res₂.toOption →
166+
(do let x ← res₁; f x).toOption = (do let x ← res₂; f x).toOption
167+
:= by
168+
cases h₁ : res₁.toOption
169+
· intro h₂
170+
simp [do_to_option_none h₁, do_to_option_none h₂.symm]
171+
· intro h₂
172+
simp [do_to_option_some h₁, do_to_option_some h₂.symm]
173+
174+
public theorem to_option_eq_do₂ {α ε} {res₁ res₂ res₃ res₄: Except ε α} (f : α → α → Except ε α) :
175+
res₁.toOption = res₃.toOption →
176+
res₂.toOption = res₄.toOption →
177+
(do let x ← res₁; let y ← res₂; f x y).toOption = (do let x ← res₃; let y ← res₄; f x y).toOption
178+
:= by
179+
intro h₁ h₂
180+
have h₁' := to_option_eq_do₁ (λ x => (do let y ← res₂ ; f x y)) h₁
181+
simp only [h₁']
182+
cases h₃ : res₃.toOption
183+
· simp [do_to_option_none h₃]
184+
· rename_i x
185+
simp [do_to_option_some h₃]
186+
have h₂' := to_option_eq_do₁ (f x) h₂
187+
simp [h₂']
188+
189+
public theorem to_option_distr_map {ε α β} {x : Except ε α} {f : α → β} :
190+
(x.map f).toOption = x.toOption.map f
191+
:= by
192+
cases x <;>
193+
simp [Except.toOption, Except.map]
194+
195+
public theorem to_option_distr_fmap {ε α β} {x : Except ε α} {f : α → β} :
196+
(f <$> x).toOption = f <$> x.toOption
197+
:= by
198+
cases x <;>
199+
simp [Except.toOption, Except.map, Functor.map]

cedar-lean/Cedar/Thm/Data/List/Lemmas.lean

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -956,6 +956,16 @@ public theorem element_error_implies_mapM_error {x : α} {xs : List α} {f : α
956956
rw [← List.mapM'_eq_mapM]
957957
exact element_error_implies_mapM'_error
958958

959+
public theorem element_to_option_none_implies_mapM_none {α β ε} {ls : List α} {x : α}
960+
{f : α → Except ε β}
961+
(h₁ : x ∈ ls)
962+
(h₂ : (f x).toOption = none) :
963+
(List.mapM f ls).toOption = none
964+
:= by
965+
rw [to_option_none] at h₂
966+
have ⟨_, he⟩ := List.element_error_implies_mapM_error h₁ h₂.choose_spec
967+
simp [he, Except.toOption]
968+
959969
public theorem mapM'_ok_eq_filterMap {α β} {f : α → Except ε β} {xs : List α} {ys : List β} :
960970
xs.mapM' f = .ok ys →
961971
xs.filterMap (λ x => match f x with | .ok y => some y | .error _ => none) = ys
@@ -1223,6 +1233,32 @@ public theorem mapM_congr [Monad m] [LawfulMonad m] {f g : α → m β} : ∀ {l
12231233
rw [← mapM'_eq_mapM, ← mapM'_eq_mapM]
12241234
exact mapM'_congr
12251235

1236+
public theorem mapM'_to_option_congr {α β ε₁ ε₂} {l : List α} {f: α → Except ε₁ β} {g: α → Except ε₂ β} :
1237+
(∀ x ∈ l, (f x).toOption = (g x).toOption) →
1238+
(List.mapM' f l).toOption = (List.mapM' g l).toOption
1239+
:= by
1240+
induction l
1241+
case nil =>
1242+
simp only [not_mem_nil, false_implies, implies_true, mapM'_nil, forall_const]
1243+
rfl
1244+
case cons head tail hᵢ =>
1245+
intro h
1246+
let ⟨h₁, h₂⟩ := forall_mem_cons.1 h ; clear h
1247+
simp only [mapM'_cons, bind_pure_comp]
1248+
cases h₃ : (f head).toOption <;> rw [h₃] at h₁
1249+
· simp [do_to_option_none h₁.symm, do_to_option_none h₃]
1250+
· simp only [do_to_option_some h₃, do_to_option_some h₁.symm]
1251+
rw [to_option_distr_fmap]
1252+
rw [to_option_distr_fmap]
1253+
rw [hᵢ h₂]
1254+
1255+
public theorem mapM_to_option_congr {α β ε₁ ε₂} {l : List α} {f: α → Except ε₁ β} {g: α → Except ε₂ β} :
1256+
(∀ x ∈ l, (f x).toOption = (g x).toOption) →
1257+
(List.mapM f l).toOption = (List.mapM g l).toOption
1258+
:= by
1259+
rw [← mapM'_eq_mapM, ← mapM'_eq_mapM]
1260+
exact mapM'_to_option_congr
1261+
12261262
/-! ### foldl -/
12271263

12281264
public theorem foldl_pmap_subtype
@@ -2106,4 +2142,32 @@ public theorem find?_filter_sorted {α : Type u} {β : Type v} [BEq α] [LawfulB
21062142
simp only [ih, List.find?_cons_eq_some, Bool.not_eq_eq_eq_not, Bool.not_true, beq_eq_false_iff_ne, and_true]
21072143
exact .inr h_k
21082144

2145+
public theorem anyM_some_implies_any {α} {xs : List α} {b : Bool} (f : α → Option Bool) (g : α → Bool) :
2146+
(∀ x b, f x = some b → g x = b) → List.anyM f xs = some b → xs.any g = b
2147+
:= by
2148+
intro h₁ h₂
2149+
induction xs generalizing b
2150+
case nil =>
2151+
simp only [anyM_nil, Option.pure_def, Option.some.injEq, Bool.false_eq] at h₂
2152+
simp only [any_nil, h₂]
2153+
case cons head tail hᵢ =>
2154+
simp only [any_cons]
2155+
simp only [anyM_cons, Option.pure_def, Option.bind_eq_bind] at h₂
2156+
generalize h₃ : f head = res
2157+
cases res <;> simp [h₃] at h₂
2158+
case some =>
2159+
split at h₂
2160+
case _ h₄ =>
2161+
simp only [Option.some.injEq, Bool.true_eq] at h₂
2162+
subst h₂ h₄
2163+
specialize h₁ head true h₃
2164+
simp only [h₁, Bool.true_or]
2165+
case _ h₄ =>
2166+
specialize hᵢ h₂
2167+
simp only [hᵢ, Bool.or_eq_right_iff_imp]
2168+
simp only [Bool.not_eq_true] at h₄
2169+
subst h₄
2170+
specialize h₁ head false h₃
2171+
simp only [h₁, Bool.false_eq_true, false_implies]
2172+
21092173
end List

cedar-lean/Cedar/Thm/TPE/Soundness/Basic.lean

Lines changed: 10 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,7 @@ open Cedar.Validation
3636
open Cedar.TPE
3737
open Cedar.Thm
3838

39-
@[simp]
40-
theorem as_value_some {r : Residual} {v : Value} :
39+
theorem asValue_some {r : Residual} {v : Value} :
4140
r.asValue = .some v ↔ (∃ ty, r = .val v ty)
4241
:= by
4342
simp only [Residual.asValue]
@@ -47,108 +46,19 @@ theorem as_value_some {r : Residual} {v : Value} :
4746
simp only [reduceCtorEq, false_iff]
4847
exact not_exists.mpr (h v)
4948

50-
theorem as_value_evaluates_to {r : Residual} {v : Value} :
51-
r.asValue = .some v → r.evaluate req es = Except.ok v
49+
theorem asValue_evaluate_val {r : Residual} {v : Value} :
50+
r.asValue = .some v → ∀ req es, r.evaluate req es = Except.ok v
5251
:= by
53-
simp only [as_value_some, forall_exists_index]
52+
simp only [asValue_some, forall_exists_index]
5453
intro _ hv
5554
simp [hv, Residual.evaluate]
5655

57-
theorem anyM_some_implies_any {α} {xs : List α} {b : Bool} (f : α → Option Bool) (g : α → Bool) :
58-
(∀ x b, f x = some b → g x = b) → List.anyM f xs = some b → xs.any g = b
56+
theorem isError_evaluate_err {r : Spec.Residual} :
57+
r.isError → ∀ req es, ∃ e, r.evaluate req es = .error e
5958
:= by
60-
intro h₁ h₂
61-
induction xs generalizing b
62-
case nil =>
63-
simp only [List.anyM, Option.pure_def, Option.some.injEq, Bool.false_eq] at h₂
64-
simp only [List.any_nil, h₂]
65-
case cons head tail hᵢ =>
66-
simp only [List.any_cons]
67-
simp only [List.anyM, Option.pure_def, Option.bind_eq_bind] at h₂
68-
generalize h₃ : f head = res
69-
cases res <;> simp [h₃] at h₂
70-
case some =>
71-
split at h₂
72-
case _ =>
73-
simp only [Option.some.injEq, Bool.true_eq] at h₂
74-
subst h₂
75-
specialize h₁ head true h₃
76-
simp only [h₁, Bool.true_or]
77-
case _ =>
78-
specialize hᵢ h₂
79-
simp only [hᵢ, Bool.or_eq_right_iff_imp]
80-
specialize h₁ head false h₃
81-
simp only [h₁, Bool.false_eq_true, false_implies]
82-
83-
theorem to_option_eq_do₁ {α β ε} {res₁ res₂: Except ε α} (f : α → Except ε β) :
84-
Except.toOption res₁ = Except.toOption res₂ →
85-
Except.toOption (do let x ← res₁; f x) = Except.toOption (do let x ← res₂; f x)
86-
:= by
87-
intro h₁
88-
simp [Except.toOption] at *
89-
split at h₁ <;>
90-
split at h₁ <;>
91-
simp at h₁
92-
case _ => subst h₁; simp only [Except.bind_ok]
93-
case _ => simp only [Except.bind_err]
94-
95-
theorem to_option_eq_map {α β ε} {res₁ res₂: Except ε α} (f : α → β) :
96-
Except.toOption res₁ = Except.toOption res₂ →
97-
Except.toOption (f <$> res₁) = Except.toOption (f <$> res₂)
98-
:= by
99-
intro h₁
100-
simp [Except.toOption] at *
101-
split at h₁ <;>
102-
split at h₁ <;>
103-
simp at h₁
104-
case _ => subst h₁; simp only
105-
case _ => simp only [Except.map_error]
106-
107-
theorem to_option_eq_do₂ {α ε} {res₁ res₂ res₃ res₄: Except ε α} (f : α → α → Except ε α) :
108-
Except.toOption res₁ = Except.toOption res₃ →
109-
Except.toOption res₂ = Except.toOption res₄ →
110-
Except.toOption (do let x ← res₁; let y ← res₂; f x y) = Except.toOption (do let x ← res₃; let y ← res₄; f x y)
111-
:= by
112-
intro h₁ h₂
113-
simp [Except.toOption] at *
114-
split at h₁ <;>
115-
split at h₁ <;>
116-
split at h₂ <;>
117-
split at h₂ <;>
118-
simp at h₁ <;>
119-
simp at h₂
120-
case _ => subst h₁; subst h₂; simp only [Except.bind_ok]
121-
case _ => simp only [Except.bind_err, Except.bind_ok]
122-
case _ => simp only [Except.bind_ok, Except.bind_err]
123-
case _ => simp only [Except.bind_err]
124-
125-
theorem to_option_eq_mapM {α β ε} {ls : List α} (f g: α → Except ε β) :
126-
(∀ x,
127-
x ∈ ls →
128-
Except.toOption (f x) = Except.toOption (g x)) →
129-
Except.toOption (List.mapM f ls) =
130-
Except.toOption (List.mapM g ls)
131-
:= by
132-
induction ls
133-
case nil => simp only [List.not_mem_nil, false_implies, implies_true, List.mapM_nil]
134-
case cons head tail hᵢ =>
135-
simp only [List.mem_cons, forall_eq_or_imp, List.mapM_cons, bind_pure_comp, and_imp]
136-
intro h
137-
simp only [Except.toOption] at h
138-
split at h <;> split at h <;> simp at h
139-
case _ heq₁ _ _ heq₂ =>
140-
subst h
141-
simp only [heq₁, Except.bind_ok, heq₂]
142-
intro h
143-
specialize hᵢ h
144-
simp only [Except.toOption] at hᵢ
145-
split at hᵢ <;> split at hᵢ <;> simp at hᵢ
146-
case _ heq₃ _ _ heq₄ =>
147-
subst hᵢ
148-
simp only [heq₃, Except.map_ok, heq₄]
149-
case _ heq₃ _ _ heq₄ =>
150-
simp only [Except.toOption, heq₃, Except.map_error, heq₄]
151-
case _ heq₁ _ _ heq₂ =>
152-
simp only [Except.toOption, heq₁, Except.bind_err, heq₂, implies_true]
59+
intro h
60+
simp only [Residual.isError] at h
61+
split at h <;> cases h
62+
simp [Spec.Residual.evaluate]
15363

15464
end Cedar.Thm

cedar-lean/Cedar/Thm/TPE/Soundness/Binary.lean

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -55,17 +55,11 @@ theorem partial_evaluate_is_sound_binary_app
5555
simp [TPE.evaluate, TPE.apply₂]
5656
split
5757
case _ heq₁ heq₂ =>
58-
-- TODO: rewrite `Residual.asValue` using standard lib so that we can use theorems to unwrap it
59-
simp [Residual.asValue] at heq₁
60-
simp [Residual.asValue] at heq₂
61-
split at heq₁ <;> cases heq₁
62-
split at heq₂ <;> cases heq₂
63-
rename_i heq₁ _ _ heq₂
64-
simp [heq₁, Residual.evaluate] at hᵢ₁
65-
simp [heq₂, Residual.evaluate] at hᵢ₂
58+
rw [as_value_evaluates_to heq₁] at hᵢ₁
59+
rw [as_value_evaluates_to heq₂] at hᵢ₂
6660
replace hᵢ₁ := to_option_right_ok' hᵢ₁
67-
replace hᵢ := to_option_right_ok' hᵢ₂
68-
simp [Residual.evaluate, hᵢ₁, hᵢ, Spec.apply₂]
61+
replace hᵢ := to_option_right_ok' hᵢ₂
62+
simp [Residual.evaluate, hᵢ₁, hᵢ, Spec.apply₂]
6963
-- TODO: rewrite one of the two binary app evaluation function so that we don't need this amount of case splits.
7064
split <;> simp [Residual.evaluate]
7165
any_goals
@@ -85,7 +79,7 @@ theorem partial_evaluate_is_sound_binary_app
8579
case _ =>
8680
simp only [Except.toOption, Residual.evaluate]
8781
case _ uid₁ uid₂ =>
88-
simp [apply₂.self, heq₁, heq₂, someOrSelf]
82+
simp [apply₂.self, someOrSelf]
8983
split
9084
case _ heq₃ =>
9185
simp only [Option.bind_eq_some_iff] at heq₃
@@ -117,9 +111,11 @@ theorem partial_evaluate_is_sound_binary_app
117111
simp only [beq_eq_false_iff_ne, ne_eq, heq₄, not_false_eq_true]
118112
simp only [this, Bool.false_or]
119113
case _ heq₃ =>
114+
rw [as_value_some] at heq₁ heq₂
115+
rw [heq₁.choose_spec, heq₂.choose_spec]
120116
simp only [Residual.evaluate, Spec.apply₂, Except.bind_ok]
121117
case _ =>
122-
simp [apply₂.self, heq₁, heq₂, someOrSelf]
118+
simp [apply₂.self, someOrSelf]
123119
split
124120
case _ uid vs _ _ _ _ _ heq₃ =>
125121
simp only [Option.bind_eq_some_iff] at heq₃
@@ -128,7 +124,7 @@ theorem partial_evaluate_is_sound_binary_app
128124
subst heq₃₂
129125
simp [Spec.inₛ]
130126
cases howt <;>
131-
(rename_i h₅; have h₆ := residual_well_typed_is_sound h₂ hwt hᵢ; rw [h₅] at h₆; cases h₆)
127+
(rename_i h₅; have h₆ := residual_well_typed_is_sound h₂ hwt hᵢ; rw [h₅] at h₆; cases h₆)
132128
rename_i h₆
133129
simp [Data.Set.mapOrErr]
134130
generalize h₇ : List.mapM Value.asEntityUID vs.elts = res
@@ -186,6 +182,8 @@ theorem partial_evaluate_is_sound_binary_app
186182
subst heq₃₂
187183
simp only [Residual.evaluate]
188184
case _ =>
185+
rw [as_value_some] at heq₁ heq₂
186+
rw [heq₁.choose_spec, heq₂.choose_spec]
189187
simp only [Spec.inₛ, Residual.evaluate, Spec.apply₂, Except.bind_ok]
190188
case _ uid _ =>
191189
simp [someOrSelf, apply₂.self]
@@ -211,7 +209,9 @@ theorem partial_evaluate_is_sound_binary_app
211209
subst heq₅
212210
simp only [Spec.hasTag, Entities.tagsOrEmpty, h₄₁, Residual.evaluate]
213211
case _ =>
214-
simp only [heq₁, heq₂, Residual.evaluate, Spec.apply₂, Except.bind_ok]
212+
rw [as_value_some] at heq₁ heq₂
213+
rw [heq₁.choose_spec, heq₂.choose_spec]
214+
simp only [Residual.evaluate, Spec.apply₂, Except.bind_ok]
215215
case _ uid _ =>
216216
simp [TPE.getTag, someOrError]
217217
split

0 commit comments

Comments
 (0)