@@ -20,6 +20,12 @@ open Nat
20
20
21
21
/-! ### mapM -/
22
22
23
+ @[simp] theorem mapM_append [Monad m] [LawfulMonad m] (f : α → m β) {l₁ l₂ : Array α} :
24
+ (l₁ ++ l₂).mapM f = (return (← l₁.mapM f) ++ (← l₂.mapM f)) := by
25
+ rcases l₁ with ⟨l₁⟩
26
+ rcases l₂ with ⟨l₂⟩
27
+ simp
28
+
23
29
theorem mapM_eq_foldlM_push [Monad m] [LawfulMonad m] (f : α → m β) (l : Array α) :
24
30
mapM f l = l.foldlM (fun acc a => return (acc.push (← f a))) #[] := by
25
31
rcases l with ⟨l⟩
@@ -37,58 +43,85 @@ theorem mapM_eq_foldlM_push [Monad m] [LawfulMonad m] (f : α → m β) (l : Arr
37
43
38
44
/-! ### foldlM and foldrM -/
39
45
40
- theorem foldlM_map [Monad m] (f : β₁ → β₂) (g : α → β₂ → m α) (l : Array β₁) (init : α) :
41
- (l.map f).foldlM g init = l.foldlM (fun x y => g x (f y)) init := by
46
+ theorem foldlM_map [Monad m] (f : β₁ → β₂) (g : α → β₂ → m α) (l : Array β₁) (init : α) (w : stop = l.size) :
47
+ (l.map f).foldlM g init 0 stop = l.foldlM (fun x y => g x (f y)) init 0 stop := by
48
+ subst w
42
49
cases l
43
- rw [List.map_toArray] -- Why doesn't this fire via `simp`?
44
50
simp [List.foldlM_map]
45
51
46
52
theorem foldrM_map [Monad m] [LawfulMonad m] (f : β₁ → β₂) (g : β₂ → α → m α) (l : Array β₁)
47
- (init : α) : (l.map f).foldrM g init = l.foldrM (fun x y => g (f x) y) init := by
53
+ (init : α) (w : start = l.size) :
54
+ (l.map f).foldrM g init start 0 = l.foldrM (fun x y => g (f x) y) init start 0 := by
55
+ subst w
48
56
cases l
49
- rw [List.map_toArray] -- Why doesn't this fire via `simp`?
50
57
simp [List.foldrM_map]
51
58
52
- theorem foldlM_filterMap [Monad m] [LawfulMonad m] (f : α → Option β) (g : γ → β → m γ) (l : Array α) (init : γ) :
53
- (l.filterMap f).foldlM g init =
59
+ theorem foldlM_filterMap [Monad m] [LawfulMonad m] (f : α → Option β) (g : γ → β → m γ)
60
+ (l : Array α) (init : γ) (w : stop = (l.filterMap f).size) :
61
+ (l.filterMap f).foldlM g init 0 stop =
54
62
l.foldlM (fun x y => match f y with | some b => g x b | none => pure x) init := by
63
+ subst w
55
64
cases l
56
- rw [List.filterMap_toArray] -- Why doesn't this fire via `simp`?
57
65
simp [List.foldlM_filterMap]
58
66
rfl
59
67
60
- theorem foldrM_filterMap [Monad m] [LawfulMonad m] (f : α → Option β) (g : β → γ → m γ) (l : Array α) (init : γ) :
61
- (l.filterMap f).foldrM g init =
68
+ theorem foldrM_filterMap [Monad m] [LawfulMonad m] (f : α → Option β) (g : β → γ → m γ)
69
+ (l : Array α) (init : γ) (w : start = (l.filterMap f).size) :
70
+ (l.filterMap f).foldrM g init start 0 =
62
71
l.foldrM (fun x y => match f x with | some b => g b y | none => pure y) init := by
72
+ subst w
63
73
cases l
64
- rw [List.filterMap_toArray] -- Why doesn't this fire via `simp`?
65
74
simp [List.foldrM_filterMap]
66
75
rfl
67
76
68
- theorem foldlM_filter [Monad m] [LawfulMonad m] (p : α → Bool) (g : β → α → m β) (l : Array α) (init : β) :
69
- (l.filter p).foldlM g init =
77
+ theorem foldlM_filter [Monad m] [LawfulMonad m] (p : α → Bool) (g : β → α → m β)
78
+ (l : Array α) (init : β) (w : stop = (l.filter p).size) :
79
+ (l.filter p).foldlM g init 0 stop =
70
80
l.foldlM (fun x y => if p y then g x y else pure x) init := by
81
+ subst w
71
82
cases l
72
- rw [List.filter_toArray] -- Why doesn't this fire via `simp`?
73
83
simp [List.foldlM_filter]
74
84
75
- theorem foldrM_filter [Monad m] [LawfulMonad m] (p : α → Bool) (g : α → β → m β) (l : Array α) (init : β) :
76
- (l.filter p).foldrM g init =
85
+ theorem foldrM_filter [Monad m] [LawfulMonad m] (p : α → Bool) (g : α → β → m β)
86
+ (l : Array α) (init : β) (w : start = (l.filter p).size) :
87
+ (l.filter p).foldrM g init start 0 =
77
88
l.foldrM (fun x y => if p x then g x y else pure y) init := by
89
+ subst w
78
90
cases l
79
- rw [List.filter_toArray] -- Why doesn't this fire via `simp`?
80
91
simp [List.foldrM_filter]
81
92
93
+ @[simp] theorem foldlM_attachWith [Monad m]
94
+ (l : Array α) {q : α → Prop } (H : ∀ a, a ∈ l → q a) {f : β → { x // q x} → m β} {b} (w : stop = l.size):
95
+ (l.attachWith q H).foldlM f b 0 stop =
96
+ l.attach.foldlM (fun b ⟨a, h⟩ => f b ⟨a, H _ h⟩) b := by
97
+ subst w
98
+ rcases l with ⟨l⟩
99
+ simp [List.foldlM_map]
100
+
101
+ @[simp] theorem foldrM_attachWith [Monad m] [LawfulMonad m]
102
+ (l : Array α) {q : α → Prop } (H : ∀ a, a ∈ l → q a) {f : { x // q x} → β → m β} {b} (w : start = l.size):
103
+ (l.attachWith q H).foldrM f b start 0 =
104
+ l.attach.foldrM (fun a acc => f ⟨a.1 , H _ a.2 ⟩ acc) b := by
105
+ subst w
106
+ rcases l with ⟨l⟩
107
+ simp [List.foldrM_map]
108
+
82
109
/-! ### forM -/
83
110
84
111
@[congr] theorem forM_congr [Monad m] {as bs : Array α} (w : as = bs)
85
112
{f : α → m PUnit} :
86
- as. forM f = bs. forM f := by
113
+ forM as f = forM bs f := by
87
114
cases as <;> cases bs
88
115
simp_all
89
116
117
+ @[simp] theorem forM_append [Monad m] [LawfulMonad m] (l₁ l₂ : Array α) (f : α → m PUnit) :
118
+ forM (l₁ ++ l₂) f = (do forM l₁ f; forM l₂ f) := by
119
+ rcases l₁ with ⟨l₁⟩
120
+ rcases l₂ with ⟨l₂⟩
121
+ simp
122
+
90
123
@[simp] theorem forM_map [Monad m] [LawfulMonad m] (l : Array α) (g : α → β) (f : β → m PUnit) :
91
- (l.map g).forM f = l. forM (fun a => f (g a)) := by
124
+ forM (l.map g) f = forM l (fun a => f (g a)) := by
92
125
cases l
93
126
simp
94
127
@@ -115,9 +148,7 @@ theorem forIn'_eq_foldlM [Monad m] [LawfulMonad m]
115
148
| .yield b => f a m b
116
149
| .done b => pure (.done b)) (ForInStep.yield init) := by
117
150
cases l
118
- rw [List.attach_toArray] -- Why doesn't this fire via `simp`?
119
- simp only [List.forIn'_toArray, List.forIn'_eq_foldlM, List.attachWith_mem_toArray, size_toArray,
120
- List.length_map, List.length_attach, List.foldlM_toArray', List.foldlM_map]
151
+ simp [List.forIn'_eq_foldlM, List.foldlM_map]
121
152
congr
122
153
123
154
/-- We can express a for loop over an array which always yields as a fold. -/
@@ -126,7 +157,6 @@ theorem forIn'_eq_foldlM [Monad m] [LawfulMonad m]
126
157
forIn' l init (fun a m b => (fun c => .yield (g a m b c)) <$> f a m b) =
127
158
l.attach.foldlM (fun b ⟨a, m⟩ => g a m b <$> f a m b) init := by
128
159
cases l
129
- rw [List.attach_toArray] -- Why doesn't this fire via `simp`?
130
160
simp [List.foldlM_map]
131
161
132
162
theorem forIn'_pure_yield_eq_foldl [Monad m] [LawfulMonad m]
@@ -191,4 +221,59 @@ theorem forIn_pure_yield_eq_foldl [Monad m] [LawfulMonad m]
191
221
cases l
192
222
simp
193
223
224
+ /-! ### Recognizing higher order functions using a function that only depends on the value. -/
225
+
226
+ /--
227
+ This lemma identifies monadic folds over lists of subtypes, where the function only depends on the value, not the proposition,
228
+ and simplifies these to the function directly taking the value.
229
+ -/
230
+ @[simp] theorem foldlM_subtype [Monad m] {p : α → Prop } {l : Array { x // p x }}
231
+ {f : β → { x // p x } → m β} {g : β → α → m β} {x : β}
232
+ (hf : ∀ b x h, f b ⟨x, h⟩ = g b x) (w : stop = l.size) :
233
+ l.foldlM f x 0 stop = l.unattach.foldlM g x 0 stop := by
234
+ subst w
235
+ rcases l with ⟨l⟩
236
+ simp
237
+ rw [List.foldlM_subtype hf]
238
+
239
+ /--
240
+ This lemma identifies monadic folds over lists of subtypes, where the function only depends on the value, not the proposition,
241
+ and simplifies these to the function directly taking the value.
242
+ -/
243
+ @[simp] theorem foldrM_subtype [Monad m] [LawfulMonad m] {p : α → Prop } {l : Array { x // p x }}
244
+ {f : { x // p x } → β → m β} {g : α → β → m β} {x : β}
245
+ (hf : ∀ x h b, f ⟨x, h⟩ b = g x b) (w : start = l.size) :
246
+ l.foldrM f x start 0 = l.unattach.foldrM g x start 0 := by
247
+ subst w
248
+ rcases l with ⟨l⟩
249
+ simp
250
+ rw [List.foldrM_subtype hf]
251
+
252
+ /--
253
+ This lemma identifies monadic maps over lists of subtypes, where the function only depends on the value, not the proposition,
254
+ and simplifies these to the function directly taking the value.
255
+ -/
256
+ @[simp] theorem mapM_subtype [Monad m] [LawfulMonad m] {p : α → Prop } {l : Array { x // p x }}
257
+ {f : { x // p x } → m β} {g : α → m β} (hf : ∀ x h, f ⟨x, h⟩ = g x) :
258
+ l.mapM f = l.unattach.mapM g := by
259
+ rcases l with ⟨l⟩
260
+ simp
261
+ rw [List.mapM_subtype hf]
262
+
263
+ -- Without `filterMapM_toArray` relating `filterMapM` on `List` and `Array` we can't prove this yet:
264
+ -- @[ simp ] theorem filterMapM_subtype [Monad m] [LawfulMonad m] {p : α → Prop} {l : Array { x // p x }}
265
+ -- {f : { x // p x } → m (Option β)} {g : α → m (Option β)} (hf : ∀ x h, f ⟨x, h⟩ = g x) :
266
+ -- l.filterMapM f = l.unattach.filterMapM g := by
267
+ -- rcases l with ⟨l⟩
268
+ -- simp
269
+ -- rw [List.filterMapM_subtype hf]
270
+
271
+ -- Without `flatMapM_toArray` relating `flatMapM` on `List` and `Array` we can't prove this yet:
272
+ -- @[ simp ] theorem flatMapM_subtype [Monad m] [LawfulMonad m] {p : α → Prop} {l : Array { x // p x }}
273
+ -- {f : { x // p x } → m (Array β)} {g : α → m (Array β)} (hf : ∀ x h, f ⟨x, h⟩ = g x) :
274
+ -- (l.flatMapM f) = l.unattach.flatMapM g := by
275
+ -- rcases l with ⟨l⟩
276
+ -- simp
277
+ -- rw [List.flatMapM_subtype hf]
278
+
194
279
end Array
0 commit comments