@@ -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
8591end 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
131137termination_by IteratorLoop.WFRel.mk wf it init
132138decreasing_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
223229instance {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
229235instance {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
235241instance {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 : Type → Type 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 : Type → Type 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+
343387end Std.Iterators
0 commit comments