|
1 | | -import Iterator.Combinators.FlatMap |
2 | | -import Iterator.Lemmas.Consumer |
| 1 | +prelude |
| 2 | +import Iterator.Lemmas.Monadic.FlatMap |
| 3 | +import Iterator.Pure.Combinators.FlatMap |
| 4 | +import Iterator.Pure.Consumers.Collect |
3 | 5 |
|
4 | | -section FlatMap |
5 | | - |
6 | | -theorem flatMapAfter_stepH {α α₂ : Type w} {m : Type w → Type w'} {β : Type v} |
7 | | - {γ : Type v'} [Monad m] [Iterator α m β] [Iterator α₂ m γ] |
8 | | - {f : β → IterM (α := α₂) m γ} {it₁ : IterM (α := α) m β} {it₂ : Option (IterM (α := α₂) m γ)} : |
9 | | - (it₁.flatMapAfter f it₂).stepH = (match it₂ with |
10 | | - | none => do |
11 | | - match (← it₁.stepH).inflate with |
12 | | - | .yield it' innerIt h => |
13 | | - pure <| .deflate <| .skip (it'.flatMapAfter f (f innerIt)) (.outerYield h) |
14 | | - | .skip it' h => |
15 | | - pure <| .deflate <| .skip (it'.flatMapAfter f none) (.outerSkip h) |
16 | | - | .done h => |
17 | | - pure <| .deflate <| .done (.outerDone h) |
18 | | - | some it₂ => do |
19 | | - match (← it₂.stepH).inflate with |
20 | | - | .yield it' out h => |
21 | | - pure <| .deflate <| .yield (it₁.flatMapAfter f it') out (.innerYield h) |
22 | | - | .skip it' h => |
23 | | - pure <| .deflate <| .skip (it₁.flatMapAfter f it') (.innerSkip h) |
24 | | - | .done h => |
25 | | - pure <| .deflate <| .skip (it₁.flatMapAfter f none) (.innerDone h)) := by |
26 | | - split |
27 | | - all_goals |
28 | | - apply bind_congr |
29 | | - intro step |
30 | | - generalize step.inflate = step |
31 | | - obtain ⟨_ | _ | _, h⟩ := step |
32 | | - all_goals rfl |
33 | | - |
34 | | -theorem flatMapAfter_step {α α₂ : Type w} {m : Type w → Type w'} {β : Type v} |
35 | | - {γ : Type w} [Monad m] [LawfulMonad m] [Iterator α m β] [Iterator α₂ m γ] |
36 | | - {f : β → IterM (α := α₂) m γ} {it₁ : IterM (α := α) m β} {it₂ : Option (IterM (α := α₂) m γ)} : |
37 | | - (it₁.flatMapAfter f it₂).step = (match it₂ with |
38 | | - | none => do |
39 | | - match (← it₁.stepH).inflate with |
40 | | - | .yield it' innerIt h => |
41 | | - pure <| .skip (it'.flatMapAfter f (f innerIt)) (.outerYield h) |
42 | | - | .skip it' h => |
43 | | - pure <| .skip (it'.flatMapAfter f none) (.outerSkip h) |
44 | | - | .done h => |
45 | | - pure <| .done (.outerDone h) |
46 | | - | some it₂ => do |
47 | | - match ← it₂.step with |
48 | | - | .yield it' out h => |
49 | | - pure <| .yield (it₁.flatMapAfter f it') out (.innerYield h) |
50 | | - | .skip it' h => |
51 | | - pure <| .skip (it₁.flatMapAfter f it') (.innerSkip h) |
52 | | - | .done h => |
53 | | - pure <| .skip (it₁.flatMapAfter f none) (.innerDone h)) := by |
54 | | - split |
55 | | - all_goals |
56 | | - simp only [IterM.step, flatMapAfter_stepH, map_eq_pure_bind, bind_assoc] |
57 | | - apply bind_congr |
58 | | - intro step |
59 | | - generalize step.inflate = step |
60 | | - obtain ⟨_ | _ | _, h⟩ := step |
61 | | - all_goals simp |
62 | | - |
63 | | -theorem flatMap_stepH {α α₂ : Type w} {m : Type w → Type w'} {β : Type v} |
64 | | - {γ : Type v'} [Monad m] [Iterator α m β] [Iterator α₂ m γ] |
65 | | - {f : β → IterM (α := α₂) m γ} {it : IterM (α := α) m β} : |
66 | | - (it.flatMap f).stepH = (do |
67 | | - match (← it.stepH).inflate with |
68 | | - | .yield it' innerIt h => |
69 | | - pure <| .deflate <| .skip (it'.flatMapAfter f (f innerIt)) (.outerYield h) |
70 | | - | .skip it' h => |
71 | | - pure <| .deflate <| .skip (it'.flatMap f) (.outerSkip h) |
72 | | - | .done h => |
73 | | - pure <| .deflate <| .done (.outerDone h)) := by |
74 | | - apply bind_congr |
75 | | - intro step |
76 | | - generalize step.inflate = step |
77 | | - obtain ⟨_ | _ | _, h⟩ := step |
78 | | - all_goals rfl |
79 | | - |
80 | | -theorem flatMap_step {α α₂ : Type w} {m : Type w → Type w'} {β : Type v} |
81 | | - {γ : Type w} [Monad m] [LawfulMonad m] [Iterator α m β] [Iterator α₂ m γ] |
82 | | - {f : β → IterM (α := α₂) m γ} {it : IterM (α := α) m β} : |
83 | | - (it.flatMap f).step = (do |
84 | | - match (← it.stepH).inflate with |
85 | | - | .yield it' innerIt h => |
86 | | - pure <| .skip (it'.flatMapAfter f (f innerIt)) (.outerYield h) |
87 | | - | .skip it' h => |
88 | | - pure <| .skip (it'.flatMap f) (.outerSkip h) |
89 | | - | .done h => |
90 | | - pure <| .done (.outerDone h)) := by |
91 | | - simp only [IterM.step, flatMap_stepH, map_eq_pure_bind, bind_assoc] |
92 | | - apply bind_congr |
93 | | - intro step |
94 | | - generalize step.inflate = step |
95 | | - obtain ⟨(_ | _ | _), h⟩ := step |
96 | | - all_goals simp |
97 | | - |
98 | | -theorem toList_flatMapAfter_some {α α₂ : Type w} {m : Type w → Type w'} {β : Type v} |
99 | | - {γ : Type w} [Monad m] [LawfulMonad m] [Iterator α m β] [Iterator α₂ m γ] |
100 | | - [Finite α m] [Finite α₂ m] |
101 | | - [IteratorToArray α m] [IteratorToArray α₂ m] |
102 | | - [LawfulIteratorToArray α m] [LawfulIteratorToArray α₂ m] |
103 | | - {f : β → IterM (α := α₂) m γ} {it₂ : IterM (α := α₂) m γ} {it₁ : IterM (α := α) m β} : |
104 | | - (it₁.flatMapAfter f (some it₂)).toList = (do |
105 | | - let l ← it₂.toList |
106 | | - let l' ← (it₁.flatMap f).toList |
107 | | - return l ++ l') := by |
108 | | - induction it₂ using IterM.induct with | step it₂ ihy ihs => |
109 | | - rw [IterM.toList_of_step, flatMapAfter_step, IterM.toList_of_step] |
110 | | - simp only [bind_assoc] |
111 | | - apply bind_congr |
112 | | - intro step |
113 | | - match step with |
114 | | - | .yield it₂' out h => |
115 | | - simp only [bind_pure_comp, pure_bind, bind_map_left, List.cons_append_fun] |
116 | | - simp only [ihy h, map_eq_pure_bind, bind_assoc, pure_bind] |
117 | | - | .skip it₂' h => |
118 | | - simp [ihs h] |
119 | | - | .done h => |
120 | | - simp only [bind_pure_comp, pure_bind, List.nil_append_fun, id_map] |
121 | | - rfl |
122 | | - |
123 | | -theorem toList_flatMap_of_stepH {α α₂ : Type w} {m : Type w → Type w'} {β : Type v} |
124 | | - {γ : Type w} [Monad m] [LawfulMonad m] [Iterator α m β] [Iterator α₂ m γ] |
125 | | - [Finite α m] [Finite α₂ m] |
126 | | - [IteratorToArray α m] [IteratorToArray α₂ m] |
127 | | - [LawfulIteratorToArray α m] [LawfulIteratorToArray α₂ m] |
128 | | - {f : β → IterM (α := α₂) m γ} {it : IterM (α := α) m β} : |
129 | | - (it.flatMap f).toList = (do |
130 | | - match (← it.stepH).inflate with |
131 | | - | .yield it' b _ => do |
132 | | - let l ← (f b).toList |
133 | | - let l' ← (it'.flatMap f).toList |
134 | | - return l ++ l' |
135 | | - | .skip it' _ => |
136 | | - (it'.flatMap f).toList |
137 | | - | .done _ => |
138 | | - pure []) := by |
139 | | - rw [IterM.toList_of_step, flatMap_step] |
140 | | - simp only [bind_assoc] |
141 | | - apply bind_congr |
142 | | - intro step |
143 | | - generalize step.inflate = step |
144 | | - match step with |
145 | | - | .yield it' out h => |
146 | | - simp [toList_flatMapAfter_some] |
147 | | - | .skip it' h => |
148 | | - simp [toList_flatMapAfter_some] |
149 | | - | .done h => |
150 | | - simp |
151 | | - |
152 | | -theorem toList_flatMap_of_pure {α α₂ : Type w} {β : Type w} |
153 | | - {γ : Type w} [Iterator α Id β] [Iterator α₂ Id γ] |
154 | | - [Finite α Id] [Finite α₂ Id] |
| 6 | +theorem Iter.toList_flatMap {α α₂ : Type w} {β : Type w} |
| 7 | + {γ : Type w} [Iterator α Id β] [Iterator α₂ Id γ] [Finite α Id] [Finite α₂ Id] |
155 | 8 | [IteratorToArray α Id] [IteratorToArray α₂ Id] |
156 | 9 | [LawfulIteratorToArray α Id] [LawfulIteratorToArray α₂ Id] |
157 | | - {f : β → IterM (α := α₂) Id γ} {it : IterM (α := α) Id β} : |
158 | | - (it.flatMap f).toList = it.toList.flatMap (fun b => (f b).toList) := by |
159 | | - induction it using IterM.induct with | step it ihy ihs => |
160 | | - rw [toList_flatMap_of_stepH, IterM.toList_of_step] |
161 | | - simp only [Id.pure_eq, Id.bind_eq, IterM.step, Id.map_eq] |
162 | | - generalize it.stepH.inflate = step |
163 | | - match step with |
164 | | - | .yield it' out h => |
165 | | - simp [ihy h] |
166 | | - | .skip it' h => |
167 | | - simp [ihs h] |
168 | | - | .done h => |
169 | | - simp |
170 | | - |
171 | | -end FlatMap |
| 10 | + {f : β → Iter (α := α₂) γ} {it : Iter (α := α) β} : |
| 11 | + (it.flatMap f).toList = it.toList.flatMap (f · |>.toList) := |
| 12 | + IterM.toList_flatMap_of_pure |
0 commit comments