Skip to content

Commit ba26a69

Browse files
committed
docstring
1 parent 6574e4c commit ba26a69

File tree

3 files changed

+64
-52
lines changed

3 files changed

+64
-52
lines changed

src/Init/Data/Iterators/Consumers/Collect.lean

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,41 +21,39 @@ Concretely, the following operations are provided:
2121
* `Iter.toListRev`, collecting the values in a list in reverse order but more efficiently
2222
* `Iter.toArray`, collecting the values in an array
2323
24-
Some operations are implemented using the `IteratorCollect` and `IteratorCollectPartial`
25-
typeclasses.
24+
Some operations are implemented using the `IteratorCollect` type class.
2625
-/
2726

2827
namespace Std.Iterators
2928

30-
@[always_inline, inline, inherit_doc IterM.toArray]
29+
@[always_inline, inherit_doc IterM.toArray]
3130
def Iter.toArray {α : Type w} {β : Type w}
3231
[Iterator α Id β] [IteratorCollect α Id Id] (it : Iter (α := α) β) : Array β :=
3332
it.toIterM.toArray.run
3433

35-
@[always_inline, inline, inherit_doc IterM.Partial.toArray, deprecated Iter.toArray (since := "2025-10-15")]
34+
@[always_inline, inherit_doc IterM.Partial.toArray, deprecated Iter.toArray (since := "2025-10-15")]
3635
def Iter.Partial.toArray {α : Type w} {β : Type w}
3736
[Iterator α Id β] [IteratorCollect α Id Id] (it : Iter.Partial (α := α) β) : Array β :=
38-
it.it.toIterM.toArray.run
37+
it.it.toArray
3938

40-
-- TODO:
41-
@[always_inline, inline, inherit_doc IterM.toListRev]
39+
@[always_inline, inherit_doc IterM.toListRev]
4240
def Iter.toListRev {α : Type w} {β : Type w}
43-
[Iterator α Id β] [Finite α Id] (it : Iter (α := α) β) : List β :=
41+
[Iterator α Id β] (it : Iter (α := α) β) : List β :=
4442
it.toIterM.toListRev.run
4543

46-
@[always_inline, inline, inherit_doc IterM.Partial.toListRev]
44+
@[always_inline, inherit_doc IterM.Partial.toListRev, deprecated Iter.toListRev (since := "2025-10-16")]
4745
def Iter.Partial.toListRev {α : Type w} {β : Type w}
4846
[Iterator α Id β] (it : Iter.Partial (α := α) β) : List β :=
49-
it.it.toIterM.allowNontermination.toListRev.run
47+
it.it.toListRev
5048

51-
@[always_inline, inline, inherit_doc IterM.toList]
49+
@[always_inline, inherit_doc IterM.toList]
5250
def Iter.toList {α : Type w} {β : Type w}
5351
[Iterator α Id β] [IteratorCollect α Id Id] (it : Iter (α := α) β) : List β :=
5452
it.toIterM.toList.run
5553

56-
@[always_inline, inline, inherit_doc IterM.Partial.toList, deprecated Iter.toList (since := "2025-10-15")]
54+
@[always_inline, inherit_doc IterM.Partial.toList, deprecated Iter.toList (since := "2025-10-15")]
5755
def Iter.Partial.toList {α : Type w} {β : Type w}
5856
[Iterator α Id β] [IteratorCollect α Id Id] (it : Iter.Partial (α := α) β) : List β :=
59-
it.it.toIterM.toList.run
57+
it.it.toList
6058

6159
end Std.Iterators

src/Init/Data/Iterators/Consumers/Monadic/Collect.lean

Lines changed: 21 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ Concretely, the following operations are provided:
2323
* `IterM.toArray`, collecting the values in an array
2424
2525
Some producers and combinators provide specialized implementations. These are captured by the
26-
`IteratorCollect` and `IteratorCollectPartial` typeclasses. They should be implemented by all
27-
types of iterators. A default implementation is provided. The typeclass `LawfulIteratorCollect`
28-
asserts that an `IteratorCollect` instance equals the default implementation.
26+
`IteratorCollect` type class. They should be implemented by all types of iterators. A default
27+
implementation is provided. The typeclass `LawfulIteratorCollect` asserts that an `IteratorCollect`
28+
instance equals the default implementation.
2929
-/
3030

3131
namespace Std.Iterators
@@ -65,7 +65,7 @@ This is an internal function used in `IteratorCollect.defaultImplementation`.
6565
It iterates over an iterator and applies `f` whenever a value is emitted before inserting the result
6666
of `f` into an array.
6767
-/
68-
@[always_inline, inline, no_expose]
68+
@[always_inline, no_expose]
6969
def IterM.DefaultConsumers.toArrayMapped {α β : Type w} {m : Type w → Type w'}
7070
{n : Type w → Type w''} [Monad n] [Iterator α m β]
7171
(lift : ⦃α : Type w⦄ → m α → n α) {γ : Type w} (f : β → n γ)
@@ -88,7 +88,7 @@ It simply iterates through the iterator using `IterM.step`, incrementally buildi
8888
data structure. For certain iterators, more efficient implementations are possible and should be
8989
used instead.
9090
-/
91-
@[always_inline, inline]
91+
@[always_inline]
9292
def IteratorCollect.defaultImplementation {α β : Type w} {m : Type w → Type w'}
9393
{n : Type w → Type w''} [Monad n] [Iterator α m β] :
9494
IteratorCollect α m n where
@@ -124,7 +124,7 @@ instance (α β : Type w) (m : Type w → Type w') (n : Type w → Type w'') [Mo
124124
/--
125125
Traverses the given iterator and stores the emitted values in an array.
126126
-/
127-
@[always_inline, inline]
127+
@[always_inline]
128128
def IterM.toArray {α β : Type w} {m : Type w → Type w'} [Monad m] [Iterator α m β]
129129
[IteratorCollect α m m] (it : IterM (α := α) m β) : m (Array β) :=
130130
IteratorCollect.toArrayMapped (fun ⦃_⦄ => id) pure it
@@ -134,59 +134,46 @@ Traverses the given iterator and stores the emitted values in an array.
134134
135135
This function is deprecated. Instead of `it.allowNontermination.toArray`, use `it.toArray`.
136136
-/
137-
@[always_inline, inline, deprecated IterM.toArray (since := "2025-10-15")]
137+
@[always_inline, deprecated IterM.toArray (since := "2025-10-15")]
138138
def IterM.Partial.toArray {α : Type w} {m : Type w → Type w'} {β : Type w} [Monad m]
139139
[Iterator α m β] (it : IterM.Partial (α := α) m β) [IteratorCollect α m m] : m (Array β) :=
140140
it.it.toArray
141141

142142
end ToArray
143143

144-
-- TODO:
145144
/--
146145
Traverses the given iterator and stores the emitted values in reverse order in a list. Because
147146
lists are prepend-only, this `toListRev` is usually more efficient that `toList`.
148-
149-
This function requires a `Finite` instance proving that the iterator will finish after a finite
150-
number of steps. If the iterator is not finite or such an instance is not available, consider using
151-
`it.allowNontermination.toListRev` instead of `it.toListRev`. However, it is not possible to
152-
formally verify the behavior of the partial variant.
153147
-/
154-
@[inline]
148+
@[always_inline]
155149
def IterM.toListRev {α : Type w} {m : Type w → Type w'} [Monad m] {β : Type w}
156-
[Iterator α m β] [Finite α m] (it : IterM (α := α) m β) : m (List β) :=
150+
[Iterator α m β] (it : IterM (α := α) m β) : m (List β) :=
157151
go it []
158152
where
159-
go [Finite α m] it bs := do
160-
match (← it.step).inflate with
161-
| .yield it' b _ => go it' (b :: bs)
162-
| .skip it' _ => go it' bs
163-
| .done _ => return bs
164-
termination_by it.finitelyManySteps
153+
@[always_inline]
154+
go (it : IterM m β) acc :=
155+
extrinsicFix₂ (fun it acc recur => do
156+
match (← it.step).inflate with
157+
| .yield it' out _ => recur it' (out :: acc)
158+
| .skip it' _ => recur it' acc
159+
| .done _ => return acc) it acc
165160

166161
/--
167162
Traverses the given iterator and stores the emitted values in reverse order in a list. Because
168163
lists are prepend-only, this `toListRev` is usually more efficient that `toList`.
169164
170-
This is a partial, potentially nonterminating, function. It is not possible to formally verify
171-
its behavior. If the iterator has a `Finite` instance, consider using `IterM.toListRev` instead.
165+
This function is deprecated. Instead of `it.allowNontermination.toListRev`, use `it.toListRev`.
172166
-/
173-
@[always_inline, inline]
167+
@[always_inline, deprecated IterM.toListRev (since := "2025-10-16")]
174168
partial def IterM.Partial.toListRev {α : Type w} {m : Type w → Type w'} [Monad m] {β : Type w}
175169
[Iterator α m β] (it : IterM.Partial (α := α) m β) : m (List β) :=
176-
go it.it []
177-
where
178-
@[specialize]
179-
go it bs := do
180-
match (← it.step).inflate with
181-
| .yield it' b _ => go it' (b :: bs)
182-
| .skip it' _ => go it' bs
183-
| .done _ => return bs
170+
it.it.toListRev
184171

185172
/--
186173
Traverses the given iterator and stores the emitted values in a list. Because
187174
lists are prepend-only, `toListRev` is usually more efficient that `toList`.
188175
-/
189-
@[always_inline, inline]
176+
@[always_inline]
190177
def IterM.toList {α : Type w} {m : Type w → Type w'} [Monad m] {β : Type w}
191178
[Iterator α m β] [IteratorCollect α m m] (it : IterM (α := α) m β) : m (List β) :=
192179
Array.toList <$> IterM.toArray it
@@ -197,7 +184,7 @@ lists are prepend-only, `toListRev` is usually more efficient that `toList`.
197184
198185
This function is deprecated. Instead of `it.allowNontermination.toList`, use `it.toList`.
199186
-/
200-
@[always_inline, inline, deprecated IterM.toList (since := "2025-10-15")]
187+
@[always_inline, deprecated IterM.toList (since := "2025-10-15")]
201188
def IterM.Partial.toList {α : Type w} {m : Type w → Type w'} [Monad m] {β : Type w}
202189
[Iterator α m β] (it : IterM.Partial (α := α) m β) [IteratorCollect α m m] :
203190
m (List β) :=

src/Init/Data/Iterators/Lemmas/Consumers/Monadic/Collect.lean

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -121,15 +121,42 @@ theorem IterM.toList_eq_match_step [Monad m] [LawfulMonad m] [Iterator α m β]
121121
intro step
122122
split <;> simp
123123

124+
theorem IterM.toListRev.go_eq [Monad m] [LawfulMonad m] [Iterator α m β] [Finite α m]
125+
{it : IterM (α := α) m β} {bs : List β} :
126+
go it bs = (do
127+
match (← it.step).inflate.val with
128+
| .yield it' out => go it' (out :: bs)
129+
| .skip it' => go it' bs
130+
| .done => return bs) := by
131+
rw [go, extrinsicFix₂_eq]
132+
· apply bind_congr; intro step
133+
cases step.inflate using PlausibleIterStep.casesOn <;> simp [go]
134+
· refine ⟨?r, ?F, ?wf, ?_⟩
135+
· exact InvImage WellFoundedRelation.rel (fun x => x.1.finitelyManySteps)
136+
· exact fun it acc G => (do
137+
match (← it.step).inflate with
138+
| .yield it' out h => G it' (out :: acc) (TerminationMeasures.Finite.rel_of_yield h)
139+
| .skip it' h => G it' acc (TerminationMeasures.Finite.rel_of_skip h)
140+
| .done _ => return acc)
141+
· apply InvImage.wf
142+
exact WellFoundedRelation.wf
143+
· intro it acc G
144+
simp only
145+
apply bind_congr; intro step
146+
cases step.inflate using PlausibleIterStep.casesOn <;> simp
147+
124148
theorem IterM.toListRev.go.aux₁ [Monad m] [LawfulMonad m] [Iterator α m β] [Finite α m]
125149
{it : IterM (α := α) m β} {b : β} {bs : List β} :
126150
IterM.toListRev.go it (bs ++ [b]) = (· ++ [b]) <$> IterM.toListRev.go it bs:= by
127-
induction it, bs using IterM.toListRev.go.induct with | _ it bs ih₁ ih₂
128-
rw [go, go, map_eq_pure_bind, bind_assoc]
151+
induction it using IterM.inductSteps generalizing bs with | step it ihy ihs
152+
rw [go_eq, go_eq, map_eq_pure_bind, bind_assoc]
129153
apply bind_congr
130154
intro step
131-
simp only [List.cons_append] at ih₁
132-
split <;> simp [*]
155+
cases step.inflate using PlausibleIterStep.casesOn
156+
· simpa using ihy ‹_› (bs := _ :: bs)
157+
· simpa using ihs ‹_›
158+
· simp
159+
133160

134161
theorem IterM.toListRev.go.aux₂ [Monad m] [LawfulMonad m] [Iterator α m β] [Finite α m]
135162
{it : IterM (α := α) m β} {acc : List β} :
@@ -148,7 +175,7 @@ theorem IterM.toListRev_eq_match_step [Monad m] [LawfulMonad m] [Iterator α m
148175
| .skip it' => it'.toListRev
149176
| .done => return []) := by
150177
simp [IterM.toListRev]
151-
rw [toListRev.go]
178+
rw [toListRev.go_eq]
152179
apply bind_congr
153180
intro step
154181
cases step.inflate using PlausibleIterStep.casesOn <;> simp [IterM.toListRev.go.aux₂]

0 commit comments

Comments
 (0)