Skip to content

Commit 2c6d658

Browse files
committed
ForIn' and size
1 parent ae83314 commit 2c6d658

File tree

6 files changed

+141
-46
lines changed

6 files changed

+141
-46
lines changed

src/Init/Data/Iterators/Basic.lean

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,13 @@ def Iter.IsPlausibleStep {α : Type w} {β : Type w} [Iterator α Id β]
372372
(it : Iter (α := α) β) (step : IterStep (Iter (α := α) β) β) : Prop :=
373373
it.toIterM.IsPlausibleStep (step.mapIterator Iter.toIterM)
374374

375+
inductive IterM.IsPlausibleIndirectOutput {α β : Type w} {m : Type w → Type w'} [Iterator α m β]
376+
: IterM (α := α) m β → β → Prop where
377+
| direct {it : IterM (α := α) m β} {out : β} : it.IsPlausibleOutput out →
378+
it.IsPlausibleIndirectOutput out
379+
| indirect {it it' : IterM (α := α) m β} {out : β} : it'.IsPlausibleSuccessorOf it →
380+
it'.IsPlausibleIndirectOutput out → it.IsPlausibleIndirectOutput out
381+
375382
/--
376383
The type of the step object returned by `Iter.step`, containing an `IterStep`
377384
and a proof that this is a plausible step for the given iterator.
@@ -429,6 +436,34 @@ def Iter.IsPlausibleSuccessorOf {α : Type w} {β : Type w} [Iterator α Id β]
429436
(it' it : Iter (α := α) β) : Prop :=
430437
it'.toIterM.IsPlausibleSuccessorOf it.toIterM
431438

439+
inductive Iter.IsPlausibleIndirectOutput {α β : Type w} [Iterator α Id β] :
440+
Iter (α := α) β → β → Prop where
441+
| direct {it : Iter (α := α) β} {out : β} : it.IsPlausibleOutput out →
442+
it.IsPlausibleIndirectOutput out
443+
| indirect {it it' : Iter (α := α) β} {out : β} : it'.IsPlausibleSuccessorOf it →
444+
it'.IsPlausibleIndirectOutput out → it.IsPlausibleIndirectOutput out
445+
446+
theorem Iter.isPlausibleIndirectOutput_iff_isPlausibleIndirectOutput_toIterM {α β : Type w}
447+
[Iterator α Id β] {it : Iter (α := α) β} {out : β} :
448+
it.IsPlausibleIndirectOutput out ↔ it.toIterM.IsPlausibleIndirectOutput out := by
449+
constructor
450+
· intro h
451+
induction h with
452+
| direct h =>
453+
exact .direct h
454+
| indirect h _ ih =>
455+
exact .indirect h ih
456+
· intro h
457+
rw [← Iter.toIter_toIterM (it := it)]
458+
generalize it.toIterM = it at ⊢ h
459+
induction h with
460+
| direct h =>
461+
exact .direct h
462+
| indirect h h' ih =>
463+
rename_i it it' out
464+
replace h : it'.toIter.IsPlausibleSuccessorOf it.toIter := h
465+
exact .indirect (α := α) h ih
466+
432467
/--
433468
Asserts that a certain iterator `it'` could plausibly be the directly succeeding iterator of another
434469
given iterator `it` while no value is emitted (see `IterStep.skip`).

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

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,11 @@ namespace Std.Iterators
2626

2727
instance (α : Type w) (β : Type w) (n : Type w → Type w') [Monad n]
2828
[Iterator α Id β] [Finite α Id] [IteratorLoop α Id n] :
29-
ForIn n (Iter (α := α) β) β where
30-
forIn it init f :=
31-
IteratorLoop.finiteForIn (fun δ (c : Id δ) => pure c.run) |>.forIn it.toIterM init f
29+
ForIn' n (Iter (α := α) β) β ⟨fun it out => it.IsPlausibleIndirectOutput out⟩ where
30+
forIn' it init f :=
31+
IteratorLoop.finiteForIn' (fun δ (c : Id δ) => pure c.run) |>.forIn' it.toIterM init
32+
fun out h acc =>
33+
f out (Iter.isPlausibleIndirectOutput_iff_isPlausibleIndirectOutput_toIterM.mpr h) acc
3234

3335
instance (α : Type w) (β : Type w) (n : Type w → Type w') [Monad n]
3436
[Iterator α Id β] [IteratorLoopPartial α Id n] :
@@ -113,4 +115,14 @@ def Iter.Partial.fold {α : Type w} {β : Type w} {γ : Type w} [Iterator α Id
113115
(init : γ) (it : Iter.Partial (α := α) β) : γ :=
114116
ForIn.forIn (m := Id) it init (fun x acc => ForInStep.yield (f acc x))
115117

118+
@[always_inline, inline, inherit_doc IterM.size]
119+
def Iter.size {α : Type w} {β : Type w} [Iterator α Id β] [IteratorSize α Id]
120+
(it : Iter (α := α) β) : Nat :=
121+
(IteratorSize.size it.toIterM).run.down
122+
123+
@[always_inline, inline, inherit_doc IterM.Partial.size]
124+
def Iter.Partial.size {α : Type w} {β : Type w} [Iterator α Id β] [IteratorSizePartial α Id]
125+
(it : Iter (α := α) β) : Nat :=
126+
(IteratorSizePartial.size it.toIterM).run.down
127+
116128
end Std.Iterators

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

Lines changed: 67 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ class IteratorLoop (α : Type w) (m : Type w → Type w') {β : Type w} [Iterato
6565
(plausible_forInStep : β → γ → ForInStep γ → Prop) →
6666
IteratorLoop.WellFounded α m plausible_forInStep →
6767
(it : IterM (α := α) m β) → γ →
68-
((b : β) → (c : γ) → n (Subtype (plausible_forInStep b c))) →
68+
((b : β) → it.IsPlausibleIndirectOutput b → (c : γ) → n (Subtype (plausible_forInStep b c))) →
6969
n γ
7070

7171
/--
@@ -80,7 +80,13 @@ class IteratorLoopPartial (α : Type w) (m : Type w → Type w') {β : Type w} [
8080
(n : Type w → Type w'') where
8181
forInPartial : ∀ (_lift : (γ : Type w) → m γ → n γ) {γ : Type w},
8282
(it : IterM (α := α) m β) → γ →
83-
((b : β) → (c : γ) → n (ForInStep γ)) → n γ
83+
((b : β) → it.IsPlausibleIndirectOutput b → (c : γ) → n (ForInStep γ)) → n γ
84+
85+
class IteratorSize (α : Type w) (m : Type w → Type w') {β : Type w} [Iterator α m β] where
86+
size : IterM (α := α) m β → m (ULift Nat)
87+
88+
class IteratorSizePartial (α : Type w) (m : Type w → Type w') {β : Type w} [Iterator α m β] where
89+
size : IterM (α := α) m β → m (ULift Nat)
8490

8591
end Typeclasses
8692

@@ -113,20 +119,20 @@ def IterM.DefaultConsumers.forIn {m : Type w → Type w'} {α : Type w} {β : Ty
113119
(plausible_forInStep : β → γ → ForInStep γ → Prop)
114120
(wf : IteratorLoop.WellFounded α m plausible_forInStep)
115121
(it : IterM (α := α) m β) (init : γ)
116-
(f : (b : β) → (c : γ) → n (Subtype (plausible_forInStep b c))) : n γ :=
122+
(f : (b : β) → it.IsPlausibleIndirectOutput b → (c : γ) → n (Subtype (plausible_forInStep b c))) : n γ :=
117123
haveI : WellFounded _ := wf
118124
letI : MonadLift m n := ⟨fun {γ} => lift γ⟩
119125
do
120126
match ← it.step with
121-
| .yield it' out _ =>
122-
match ← f out init with
127+
| .yield it' out h =>
128+
match ← f out (.direct ⟨_, h⟩) init with
123129
| ⟨.yield c, _⟩ =>
124130
IterM.DefaultConsumers.forIn lift _ plausible_forInStep wf it' c
125-
(fun out acc => f out acc)
131+
(fun out h' acc => f out (.indirect ⟨_, rfl, h⟩ h') acc)
126132
| ⟨.done c, _⟩ => return c
127-
| .skip it' _ =>
133+
| .skip it' h =>
128134
IterM.DefaultConsumers.forIn lift _ plausible_forInStep wf it' init
129-
(fun out acc => f out acc)
135+
(fun out h' acc => f out (.indirect ⟨_, rfl, h⟩ h') acc)
130136
| .done _ => return init
131137
termination_by IteratorLoop.WFRel.mk wf it init
132138
decreasing_by
@@ -161,19 +167,19 @@ partial def IterM.DefaultConsumers.forInPartial {m : Type w → Type w'} {α : T
161167
{n : Type w → Type w''} [Monad n]
162168
(lift : ∀ γ, m γ → n γ) (γ : Type w)
163169
(it : IterM (α := α) m β) (init : γ)
164-
(f : (b : β) → (c : γ) → n (ForInStep γ)) : n γ :=
170+
(f : (b : β) → it.IsPlausibleIndirectOutput b → (c : γ) → n (ForInStep γ)) : n γ :=
165171
letI : MonadLift m n := ⟨fun {γ} => lift γ⟩
166172
do
167173
match ← it.step with
168-
| .yield it' out _ =>
169-
match ← f out init with
174+
| .yield it' out h =>
175+
match ← f out (.direct ⟨_, h⟩) init with
170176
| .yield c =>
171177
IterM.DefaultConsumers.forInPartial lift _ it' c
172-
fun out acc => f out acc
178+
fun out h' acc => f out (.indirect ⟨_, rfl, h⟩ h') acc
173179
| .done c => return c
174-
| .skip it' _ =>
180+
| .skip it' h =>
175181
IterM.DefaultConsumers.forInPartial lift _ it' init
176-
fun out acc => f out acc
182+
fun out h' acc => f out (.indirect ⟨_, rfl, h⟩ h') acc
177183
| .done _ => return init
178184

179185
/--
@@ -208,28 +214,28 @@ theorem IteratorLoop.wellFounded_of_finite {m : Type w → Type w'}
208214
exact WellFoundedRelation.wf
209215

210216
/--
211-
This `ForIn`-style loop construct traverses a finite iterator using an `IteratorLoop` instance.
217+
This `ForIn'`-style loop construct traverses a finite iterator using an `IteratorLoop` instance.
212218
-/
213219
@[always_inline, inline]
214-
def IteratorLoop.finiteForIn {m : Type w → Type w'} {n : Type w → Type w''}
220+
def IteratorLoop.finiteForIn' {m : Type w → Type w'} {n : Type w → Type w''}
215221
{α : Type w} {β : Type w} [Iterator α m β] [Finite α m] [IteratorLoop α m n]
216222
(lift : ∀ γ, m γ → n γ) :
217-
ForIn n (IterM (α := α) m β) β where
218-
forIn {γ} [Monad n] it init f :=
223+
ForIn' n (IterM (α := α) m β) βfun it out => it.IsPlausibleIndirectOutput out⟩ where
224+
forIn' {γ} [Monad n] it init f :=
219225
IteratorLoop.forIn (α := α) (m := m) lift γ (fun _ _ _ => True)
220226
wellFounded_of_finite
221-
it init (fun out acc => (⟨·, .intro⟩) <$> f out acc)
227+
it init (fun out h acc => (⟨·, .intro⟩) <$> f out h acc)
222228

223229
instance {m : Type w → Type w'} {n : Type w → Type w''}
224230
{α : Type w} {β : Type w} [Iterator α m β] [Finite α m] [IteratorLoop α m n]
225231
[MonadLiftT m n] :
226-
ForIn n (IterM (α := α) m β) β :=
227-
IteratorLoop.finiteForIn (fun _ => monadLift)
232+
ForIn' n (IterM (α := α) m β) βfun it out => it.IsPlausibleIndirectOutput out⟩ :=
233+
IteratorLoop.finiteForIn' (fun _ => monadLift)
228234

229235
instance {m : Type w → Type w'} {n : Type w → Type w''}
230236
{α : Type w} {β : Type w} [Iterator α m β] [IteratorLoopPartial α m n] [MonadLiftT m n] :
231-
ForIn n (IterM.Partial (α := α) m β) β where
232-
forIn it init f :=
237+
ForIn' n (IterM.Partial (α := α) m β) βfun it out => it.it.IsPlausibleIndirectOutput out⟩ where
238+
forIn' it init f :=
233239
IteratorLoopPartial.forInPartial (α := α) (m := m) (fun _ => monadLift) it.it init f
234240

235241
instance {m : Type w → Type w'} {n : Type w → Type w''}
@@ -340,4 +346,42 @@ def IterM.Partial.drain {α : Type w} {m : Type w → Type w'} [Monad m] {β : T
340346
m PUnit :=
341347
it.fold (γ := PUnit) (fun _ _ => .unit) .unit
342348

349+
section Size
350+
351+
@[always_inline, inline]
352+
def IterM.DefaultConsumers.size {α : Type w} {m : Type w → Type w'} [Monad m] {β : Type w}
353+
[Iterator α m β] [IteratorLoop α m m] [Finite α m] (it : IterM (α := α) m β) :
354+
m (ULift Nat) :=
355+
it.fold (init := .up 0) fun acc _ => .up (acc.down + 1)
356+
357+
@[always_inline, inline]
358+
def IterM.DefaultConsumers.sizePartial {α : Type w} {m : Type w → Type w'} [Monad m] {β : Type w}
359+
[Iterator α m β] [IteratorLoopPartial α m m] (it : IterM (α := α) m β) :
360+
m (ULift Nat) :=
361+
it.allowNontermination.fold (init := .up 0) fun acc _ => .up (acc.down + 1)
362+
363+
@[always_inline, inline]
364+
instance IteratorSize.defaultImplementation {α β : Type w} {m : Type w → Type w'} [Monad m]
365+
[Iterator α m β] [Finite α m] [IteratorLoop α m m] :
366+
IteratorSize α m where
367+
size := IterM.DefaultConsumers.size
368+
369+
@[always_inline, inline]
370+
instance IteratorSize.Partial.defaultImplementation {α β : Type w} {m : Type w → Type w'} [Monad m]
371+
[Iterator α m β] [Finite α m] [IteratorLoopPartial α m m] :
372+
IteratorSizePartial α m where
373+
size := IterM.DefaultConsumers.sizePartial
374+
375+
@[always_inline, inline]
376+
def IterM.size {α : Type} {m : TypeType w'} {β : Type} [Iterator α m β] [Monad m]
377+
(it : IterM (α := α) m β) [IteratorSize α m] : m Nat :=
378+
ULift.down <$> IteratorSize.size it
379+
380+
@[always_inline, inline]
381+
def IterM.Partial.size {α : Type} {m : TypeType w'} {β : Type} [Iterator α m β] [Monad m]
382+
(it : IterM.Partial (α := α) m β) [IteratorSizePartial α m] : m Nat :=
383+
ULift.down <$> IteratorSizePartial.size it.it
384+
385+
end Size
386+
343387
end Std.Iterators

src/Init/Data/Iterators/Lemmas/Consumers/Loop.lean

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,25 @@ import Init.Data.Iterators.Consumers.Loop
1010

1111
namespace Std.Iterators
1212

13+
theorem Iter.forIn'_eq {α β : Type w} [Iterator α Id β] [Finite α Id]
14+
{m : Type w → Type w''} [Monad m] [IteratorLoop α Id m] [hl : LawfulIteratorLoop α Id m]
15+
{γ : Type w} {it : Iter (α := α) β} {init : γ}
16+
{f : (b : β) → it.IsPlausibleIndirectOutput b → γ → m (ForInStep γ)} :
17+
ForIn'.forIn' it init f =
18+
IterM.DefaultConsumers.forIn (fun _ c => pure c.run) γ (fun _ _ _ => True)
19+
IteratorLoop.wellFounded_of_finite it.toIterM init
20+
(fun out h acc => (⟨·, .intro⟩) <$>
21+
f out (Iter.isPlausibleIndirectOutput_iff_isPlausibleIndirectOutput_toIterM.mpr h) acc) := by
22+
cases hl.lawful; rfl
23+
1324
theorem Iter.forIn_eq {α β : Type w} [Iterator α Id β] [Finite α Id]
1425
{m : Type w → Type w''} [Monad m] [IteratorLoop α Id m] [hl : LawfulIteratorLoop α Id m]
1526
{γ : Type w} {it : Iter (α := α) β} {init : γ}
1627
{f : (b : β) → γ → m (ForInStep γ)} :
1728
ForIn.forIn it init f =
1829
IterM.DefaultConsumers.forIn (fun _ c => pure c.run) γ (fun _ _ _ => True)
1930
IteratorLoop.wellFounded_of_finite it.toIterM init
20-
(fun out acc => (⟨·, .intro⟩) <$>
31+
(fun out _ acc => (⟨·, .intro⟩) <$>
2132
f out acc) := by
2233
cases hl.lawful; rfl
2334

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

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,18 @@ theorem IterM.DefaultConsumers.forIn'_eq_match_step {α β : Type w} {m : Type w
1818
{plausible_forInStep : β → γ → ForInStep γ → Prop}
1919
{wf : IteratorLoop.WellFounded α m plausible_forInStep}
2020
{it : IterM (α := α) m β} {init : γ}
21-
{f : (b : β) → (c : γ) → n (Subtype (plausible_forInStep b c))} :
21+
{f : (b : β) → it.IsPlausibleIndirectOutput b → (c : γ) → n (Subtype (plausible_forInStep b c))} :
2222
IterM.DefaultConsumers.forIn lift γ plausible_forInStep wf it init f = (do
2323
match ← lift _ it.step with
24-
| .yield it' out _ =>
25-
match ← f out init with
24+
| .yield it' out h =>
25+
match ← f out (.direct ⟨_, h⟩) init with
2626
| ⟨.yield c, _⟩ =>
2727
IterM.DefaultConsumers.forIn lift _ plausible_forInStep wf it' c
28-
fun out acc => f out acc
28+
fun out h'' acc => f out (.indirect ⟨_, rfl, h⟩ h'') acc
2929
| ⟨.done c, _⟩ => return c
30-
| .skip it' _ =>
30+
| .skip it' h =>
3131
IterM.DefaultConsumers.forIn lift _ plausible_forInStep wf it' init
32-
fun out acc => f out acc
32+
fun out h' acc => f out (.indirect ⟨_, rfl, h⟩ h') acc
3333
| .done _ => return init) := by
3434
rw [forIn]
3535
apply bind_congr
@@ -39,17 +39,17 @@ theorem IterM.DefaultConsumers.forIn'_eq_match_step {α β : Type w} {m : Type w
3939
theorem IterM.forIn'_eq {α β : Type w} {m : Type w → Type w'} [Iterator α m β] [Finite α m]
4040
{n : Type w → Type w''} [Monad n] [IteratorLoop α m n] [hl : LawfulIteratorLoop α m n]
4141
[MonadLiftT m n] {γ : Type w} {it : IterM (α := α) m β} {init : γ}
42-
{f : (b : β) → γ → n (ForInStep γ)} :
43-
ForIn.forIn it init f = IterM.DefaultConsumers.forIn (fun _ => monadLift) γ (fun _ _ _ => True)
44-
IteratorLoop.wellFounded_of_finite it init ((⟨·, .intro⟩) <$> f · ·) := by
42+
{f : (b : β) → it.IsPlausibleIndirectOutput b → γ → n (ForInStep γ)} :
43+
ForIn'.forIn' it init f = IterM.DefaultConsumers.forIn (fun _ => monadLift) γ (fun _ _ _ => True)
44+
IteratorLoop.wellFounded_of_finite it init ((⟨·, .intro⟩) <$> f · · ·) := by
4545
cases hl.lawful; rfl
4646

4747
theorem IterM.forIn_eq {α β : Type w} {m : Type w → Type w'} [Iterator α m β] [Finite α m]
4848
{n : Type w → Type w''} [Monad n] [IteratorLoop α m n] [hl : LawfulIteratorLoop α m n]
4949
[MonadLiftT m n] {γ : Type w} {it : IterM (α := α) m β} {init : γ}
5050
{f : β → γ → n (ForInStep γ)} :
5151
ForIn.forIn it init f = IterM.DefaultConsumers.forIn (fun _ => monadLift) γ (fun _ _ _ => True)
52-
IteratorLoop.wellFounded_of_finite it init (fun out acc => (⟨·, .intro⟩) <$> f out acc) := by
52+
IteratorLoop.wellFounded_of_finite it init (fun out _ acc => (⟨·, .intro⟩) <$> f out acc) := by
5353
cases hl.lawful; rfl
5454

5555
theorem IterM.forIn_eq_match_step {α β : Type w} {m : Type w → Type w'} [Iterator α m β]

src/Std/Data/Iterators/Combinators/Monadic/TakeWhile.lean

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -239,14 +239,7 @@ instance TakeWhile.instIteratorLoop [Monad m] [Monad n] [Iterator α m β]
239239

240240
instance TakeWhile.instIteratorForPartial [Monad m] [Monad n] [Iterator α m β]
241241
[IteratorLoopPartial α m n] [MonadLiftT m n] {P} :
242-
IteratorLoopPartial (TakeWhile α m β P) m n where
243-
forInPartial lift {γ} it init f := do
244-
IteratorLoopPartial.forInPartial lift it.internalState.inner (γ := γ)
245-
init
246-
fun out acc => do match ← (P out).operation with
247-
| ⟨.up true, _⟩ => match ← f out acc with
248-
| .yield c => pure (.yield c)
249-
| .done c => pure (.done c)
250-
| ⟨.up false, _⟩ => pure (.done acc)
242+
IteratorLoopPartial (TakeWhile α m β P) m n :=
243+
.defaultImplementation
251244

252245
end Std.Iterators

0 commit comments

Comments
 (0)