@@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
44Authors: Paul Reichert
55-/
66prelude
7+ import Init.Data.Option.Lemmas
78import Std.Data.Iterators.Basic
89import Std.Data.Iterators.Consumers.Collect
910import Std.Data.Iterators.Consumers.Loop
@@ -58,32 +59,42 @@ instance Zip.instIterator [Monad m] :
5859 | .done hp =>
5960 pure <| .done (.doneRight hm hp)
6061
61- @[inline]
62+ /--
63+ Given two iterators `left` and `right`, `left.zip right` is an iterator that yields pairs of
64+ outputs of `left` and `right`. When one of them terminates,
65+ the `zip` iterator will also terminate.
66+
67+ **Marble diagram:**
68+
69+ ```text
70+ left --a ---b --c
71+ right --x --y --⊥
72+ left.zip right -----(a, x)------(b, y)-----⊥
73+ ```
74+
75+ **Termination properties:**
76+
77+ * `Finite` instance: only if either `left` or `right` is finite and the other is productive
78+ * `Productive` instance: only if `left` and `right` are productive
79+
80+ There are situations where `left.zip right` is finite (or productive) but none of the instances
81+ above applies. For example, if the computation happens in an `Except` monad and `left` immediately
82+ fails when calling `step`, then `left.zip right` will also do so. In such a case, the `Finite`
83+ (or `Productive`) instance needs to be proved manually.
84+
85+ **Performance:**
86+
87+ This combinator incurs an additional O(1) cost with each step taken by `left` or `right`.
88+
89+ Right now, the compiler does not unbox the internal state, leading to worse performance than
90+ possible.
91+ -/
92+ @[always_inline, inline]
6293def IterM.zip
6394 (left : IterM (α := α₁) m β₁) (right : IterM (α := α₂) m β₂) :
6495 IterM (α := Zip α₁ m α₂ β₂) m (β₁ × β₂) :=
6596 toIterM ⟨left, none, right⟩ m _
6697
67- -- TODO: put this into core. This is also duplicated in FlatMap
68- theorem Zip.wellFounded_optionLt {α} {rel : α → α → Prop } (h : WellFounded rel) :
69- WellFounded (Option.lt rel) := by
70- refine ⟨?_⟩
71- intro x
72- have hn : Acc (Option.lt rel) none := by
73- refine Acc.intro none ?_
74- intro y hyx
75- cases y <;> cases hyx
76- cases x
77- · exact hn
78- · rename_i x
79- induction h.apply x
80- rename_i x' h ih
81- refine Acc.intro _ ?_
82- intro y hyx'
83- cases y
84- · exact hn
85- · exact ih _ hyx'
86-
8798variable (m) in
8899def Zip.Rel₁ [Finite α₁ m] [Productive α₂ m] :
89100 IterM (α := Zip α₁ m α₂ β₂) m (β₁ × β₂) → IterM (α := Zip α₁ m α₂ β₂) m (β₁ × β₂) → Prop :=
@@ -119,7 +130,7 @@ def Zip.instFinitenessRelation₁ [Monad m] [Finite α₁ m] [Productive α₂ m
119130 refine ⟨fun (a, b) => Prod.lexAccessible (WellFounded.apply ?_ a) (WellFounded.apply ?_) b⟩
120131 · exact WellFoundedRelation.wf
121132 · refine ⟨fun (a, b) => Prod.lexAccessible (WellFounded.apply ?_ a) (WellFounded.apply ?_) b⟩
122- · apply Zip.wellFounded_optionLt
133+ · apply Option.wellFounded_lt
123134 exact emptyWf.wf
124135 · exact WellFoundedRelation.wf
125136 subrelation {it it'} h := by
@@ -151,35 +162,12 @@ instance Zip.instFinite₁ [Monad m] [Finite α₁ m] [Productive α₂ m] :
151162 Finite (Zip α₁ m α₂ β₂) m :=
152163 Finite.of_finitenessRelation Zip.instFinitenessRelation₁
153164
154- def Zip.lt_with_top {α} (r : α → α → Prop ) : Option α → Option α → Prop
155- | none, _ => false
156- | some _, none => true
157- | some a', some a => r a' a
158-
159- theorem Zip.wellFounded_lt_with_top {α} {r : α → α → Prop } (h : WellFounded r) :
160- WellFounded (lt_with_top r) := by
161- refine ⟨?_⟩
162- intro x
163- constructor
164- intro x' hlt
165- match x' with
166- | none => contradiction
167- | some x' =>
168- clear hlt
169- induction h.apply x'
170- rename_i ih
171- constructor
172- intro x'' hlt'
173- match x'' with
174- | none => contradiction
175- | some x'' => exact ih x'' hlt'
176-
177165variable (m) in
178166def Zip.Rel₂ [Productive α₁ m] [Finite α₂ m] :
179167 IterM (α := Zip α₁ m α₂ β₂) m (β₁ × β₂) → IterM (α := Zip α₁ m α₂ β₂) m (β₁ × β₂) → Prop :=
180168 InvImage (Prod.Lex
181169 IterM.TerminationMeasures.Finite.Rel
182- (Prod.Lex (Zip.lt_with_top emptyRelation) IterM.TerminationMeasures.Productive.Rel))
170+ (Prod.Lex (Option.SomeLtNone.lt emptyRelation) IterM.TerminationMeasures.Productive.Rel))
183171 (fun it => (it.internalState.right.finitelyManySteps, (it.internalState.memoizedLeft, it.internalState.left.finitelyManySkips)))
184172
185173theorem Zip.rel₂_of_right [Productive α₁ m] [Finite α₂ m] {it' it : IterM (α := Zip α₁ m α₂ β₂) m (β₁ × β₂)}
@@ -188,7 +176,7 @@ theorem Zip.rel₂_of_right [Productive α₁ m] [Finite α₂ m] {it' it : Iter
188176
189177theorem Zip.rel₂_of_memoizedLeft [Productive α₁ m] [Finite α₂ m]
190178 {right : IterM (α := α₂) m β₂} {b' b} {left' left : IterM (α := α₁) m β₁}
191- (h : lt_with_top emptyRelation b' b) :
179+ (h : Option.SomeLtNone.lt emptyRelation b' b) :
192180 Zip.Rel₂ m ⟨left, b', right⟩ ⟨left', b, right⟩ :=
193181 Prod.Lex.right _ <| Prod.Lex.left _ _ h
194182
@@ -208,7 +196,7 @@ def Zip.instFinitenessRelation₂ [Monad m] [Productive α₁ m] [Finite α₂ m
208196 refine ⟨fun (a, b) => Prod.lexAccessible (WellFounded.apply ?_ a) (WellFounded.apply ?_) b⟩
209197 · exact WellFoundedRelation.wf
210198 · refine ⟨fun (a, b) => Prod.lexAccessible (WellFounded.apply ?_ a) (WellFounded.apply ?_) b⟩
211- · apply Zip.wellFounded_lt_with_top
199+ · apply Option.SomeLtNone.wellFounded_lt
212200 exact emptyWf.wf
213201 · exact WellFoundedRelation.wf
214202 subrelation {it it'} h := by
@@ -217,7 +205,7 @@ def Zip.instFinitenessRelation₂ [Monad m] [Productive α₁ m] [Finite α₂ m
217205 case yieldLeft hm it' out hp =>
218206 cases h
219207 apply Zip.rel₂_of_memoizedLeft
220- simp_all [Zip.lt_with_top ]
208+ simp_all [Option.SomeLtNone.lt ]
221209 case skipLeft hm it' hp =>
222210 cases h
223211 apply Zip.rel₂_of_left
@@ -244,12 +232,12 @@ variable (m) in
244232def Zip.Rel₃ [Productive α₁ m] [Productive α₂ m] :
245233 IterM (α := Zip α₁ m α₂ β₂) m (β₁ × β₂) → IterM (α := Zip α₁ m α₂ β₂) m (β₁ × β₂) → Prop :=
246234 InvImage (Prod.Lex
247- (lt_with_top emptyRelation)
235+ (Option.SomeLtNone.lt emptyRelation)
248236 (Prod.Lex (IterM.TerminationMeasures.Productive.Rel) IterM.TerminationMeasures.Productive.Rel))
249237 (fun it => (it.internalState.memoizedLeft, (it.internalState.left.finitelyManySkips, it.internalState.right.finitelyManySkips)))
250238
251239theorem Zip.rel₃_of_memoizedLeft [Productive α₁ m] [Productive α₂ m] {it' it : IterM (α := Zip α₁ m α₂ β₂) m (β₁ × β₂)}
252- (h : lt_with_top emptyRelation it'.internalState.memoizedLeft it.internalState.memoizedLeft) :
240+ (h : Option.SomeLtNone.lt emptyRelation it'.internalState.memoizedLeft it.internalState.memoizedLeft) :
253241 Zip.Rel₃ m it' it :=
254242 Prod.Lex.left _ _ h
255243
@@ -273,7 +261,7 @@ def Zip.instProductivenessRelation [Monad m] [Productive α₁ m] [Productive α
273261 wf := by
274262 apply InvImage.wf
275263 refine ⟨fun (a, b) => Prod.lexAccessible (WellFounded.apply ?_ a) (WellFounded.apply ?_) b⟩
276- · apply Zip.wellFounded_lt_with_top
264+ · apply Option.SomeLtNone.wellFounded_lt
277265 exact emptyWf.wf
278266 · refine ⟨fun (a, b) => Prod.lexAccessible (WellFounded.apply ?_ a) (WellFounded.apply ?_) b⟩
279267 · exact WellFoundedRelation.wf
@@ -282,7 +270,7 @@ def Zip.instProductivenessRelation [Monad m] [Productive α₁ m] [Productive α
282270 cases h
283271 case yieldLeft hm it' out hp =>
284272 apply Zip.rel₃_of_memoizedLeft
285- simp [lt_with_top , hm]
273+ simp [Option.SomeLtNone.lt , hm]
286274 case skipLeft hm it' hp =>
287275 obtain ⟨⟨left, memoizedLeft, right⟩⟩ := it
288276 simp only at hm
0 commit comments