refactor: partially move iterators to Init (#8767)

This PR moves parts of the iterator library from `Std` to `Init`. The
reason is that the polymorphic range API must be in `Init` and it
depends on the iterators.
This commit is contained in:
Paul Reichert 2025-06-18 12:08:04 +02:00 committed by GitHub
parent f0fdab86bb
commit 86eded35db
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
62 changed files with 980 additions and 803 deletions

View file

@ -46,3 +46,4 @@ import Init.Data.NeZero
import Init.Data.Function
import Init.Data.RArray
import Init.Data.Vector
import Init.Data.Iterators

View file

@ -0,0 +1,19 @@
/-
Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Paul Reichert
-/
module
prelude
import Init.Data.Iterators.Basic
import Init.Data.Iterators.PostconditionMonad
import Init.Data.Iterators.Consumers
import Init.Data.Iterators.Lemmas
import Init.Data.Iterators.Internal
/-!
# Iterators
See `Std.Data.Iterators` for an overview over the iterator API.
-/

View file

@ -3,6 +3,8 @@ Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Paul Reichert
-/
module
prelude
import Init.Core
import Init.Classical
@ -31,7 +33,7 @@ See `Std.Data.Iterators.Producers` for ways to iterate over common data structur
By convention, the monadic iterator associated with an object can be obtained via dot notation.
For example, `List.iterM IO` creates an iterator over a list in the monad `IO`.
See `Std.Data.Iterators.Consumers` for ways to use an iterator. For example, `it.toList` will
See `Init.Data.Iterators.Consumers` for ways to use an iterator. For example, `it.toList` will
convert a provably finite iterator `it` into a list and `it.allowNontermination.toList` will
do so even if finiteness cannot be proved. It is also always possible to manually iterate using
`it.step`, relying on the termination measures `it.finitelyManySteps` and `it.finitelyManySkips`.
@ -75,7 +77,7 @@ See `Std.Data.Iterators.Producers` for ways to iterate over common data structur
By convention, the monadic iterator associated with an object can be obtained via dot notation.
For example, `List.iterM IO` creates an iterator over a list in the monad `IO`.
See `Std.Data.Iterators.Consumers` for ways to use an iterator. For example, `it.toList` will
See `Init.Data.Iterators.Consumers` for ways to use an iterator. For example, `it.toList` will
convert a provably finite iterator `it` into a list and `it.allowNontermination.toList` will
do so even if finiteness cannot be proved. It is also always possible to manually iterate using
`it.step`, relying on the termination measures `it.finitelyManySteps` and `it.finitelyManySkips`.
@ -111,12 +113,14 @@ structure Iter {α : Type w} (β : Type w) where
Converts a pure iterator (`Iter β`) into a monadic iterator (`IterM Id β`) in the
identity monad `Id`.
-/
@[expose]
def Iter.toIterM {α : Type w} {β : Type w} (it : Iter (α := α) β) : IterM (α := α) Id β :=
⟨it.internalState⟩
/--
Converts a monadic iterator (`IterM Id β`) over `Id` into a pure iterator (`Iter β`).
-/
@[expose]
def IterM.toIter {α : Type w} {β : Type w} (it : IterM (α := α) Id β) : Iter (α := α) β :=
⟨it.internalState⟩
@ -170,6 +174,7 @@ inductive IterStep (α β) where
Returns the succeeding iterator stored in an iterator step or `none` if the step is `.done`
and the iterator has finished.
-/
@[expose]
def IterStep.successor : IterStep α β → Option α
| .yield it _ => some it
| .skip it => some it
@ -179,7 +184,7 @@ def IterStep.successor : IterStep α β → Option α
If present, applies `f` to the iterator of an `IterStep` and replaces the iterator
with the result of the application of `f`.
-/
@[always_inline, inline]
@[always_inline, inline, expose]
def IterStep.mapIterator {α' : Type u'} (f : αα') : IterStep α β → IterStep α' β
| .yield it out => .yield (f it) out
| .skip it => .skip (f it)
@ -224,12 +229,13 @@ of another state. Having this proof bundled up with the step is important for te
See `IterM.Step` and `Iter.Step` for the concrete choice of the plausibility predicate.
-/
@[expose]
def PlausibleIterStep (IsPlausibleStep : IterStep α β → Prop) := Subtype IsPlausibleStep
/--
Match pattern for the `yield` case. See also `IterStep.yield`.
-/
@[match_pattern, simp]
@[match_pattern, simp, expose]
def PlausibleIterStep.yield {IsPlausibleStep : IterStep α β → Prop}
(it' : α) (out : β) (h : IsPlausibleStep (.yield it' out)) :
PlausibleIterStep IsPlausibleStep :=
@ -238,7 +244,7 @@ def PlausibleIterStep.yield {IsPlausibleStep : IterStep α β → Prop}
/--
Match pattern for the `skip` case. See also `IterStep.skip`.
-/
@[match_pattern, simp]
@[match_pattern, simp, expose]
def PlausibleIterStep.skip {IsPlausibleStep : IterStep α β → Prop}
(it' : α) (h : IsPlausibleStep (.skip it')) : PlausibleIterStep IsPlausibleStep :=
⟨.skip it', h⟩
@ -246,7 +252,7 @@ def PlausibleIterStep.skip {IsPlausibleStep : IterStep α β → Prop}
/--
Match pattern for the `done` case. See also `IterStep.done`.
-/
@[match_pattern, simp]
@[match_pattern, simp, expose]
def PlausibleIterStep.done {IsPlausibleStep : IterStep α β → Prop}
(h : IsPlausibleStep .done) : PlausibleIterStep IsPlausibleStep :=
⟨.done, h⟩
@ -283,7 +289,7 @@ section Monadic
/--
Converts wraps the state of an iterator into an `IterM` object.
-/
@[always_inline, inline]
@[always_inline, inline, expose]
def toIterM {α : Type w} (it : α) (m : Type w → Type w') (β : Type w) :
IterM (α := α) m β :=
⟨it⟩
@ -302,6 +308,7 @@ theorem internalState_toIterM {α m β} (it : α) :
Asserts that certain step is plausibly the successor of a given iterator. What "plausible" means
is up to the `Iterator` instance but it should be strong enough to allow termination proofs.
-/
@[expose]
abbrev IterM.IsPlausibleStep {α : Type w} {m : Type w → Type w'} {β : Type w} [Iterator α m β] :
IterM (α := α) m β → IterStep (IterM (α := α) m β) β → Prop :=
Iterator.IsPlausibleStep (α := α) (m := m)
@ -310,6 +317,7 @@ abbrev IterM.IsPlausibleStep {α : Type w} {m : Type w → Type w'} {β : Type w
The type of the step object returned by `IterM.step`, containing an `IterStep`
and a proof that this is a plausible step for the given iterator.
-/
@[expose]
abbrev IterM.Step {α : Type w} {m : Type w → Type w'} {β : Type w} [Iterator α m β]
(it : IterM (α := α) m β) :=
PlausibleIterStep it.IsPlausibleStep
@ -318,6 +326,7 @@ abbrev IterM.Step {α : Type w} {m : Type w → Type w'} {β : Type w} [Iterator
Asserts that a certain output value could plausibly be emitted by the given iterator in its next
step.
-/
@[expose]
def IterM.IsPlausibleOutput {α : Type w} {m : Type w → Type w'} {β : Type w} [Iterator α m β]
(it : IterM (α := α) m β) (out : β) : Prop :=
∃ it', it.IsPlausibleStep (.yield it' out)
@ -326,6 +335,7 @@ def IterM.IsPlausibleOutput {α : Type w} {m : Type w → Type w'} {β : Type w}
Asserts that a certain iterator `it'` could plausibly be the directly succeeding iterator of another
given iterator `it`.
-/
@[expose]
def IterM.IsPlausibleSuccessorOf {α : Type w} {m : Type w → Type w'} {β : Type w} [Iterator α m β]
(it' it : IterM (α := α) m β) : Prop :=
∃ step, step.successor = some it' ∧ it.IsPlausibleStep step
@ -334,6 +344,7 @@ def IterM.IsPlausibleSuccessorOf {α : Type w} {m : Type w → Type w'} {β : Ty
Asserts that a certain iterator `it'` could plausibly be the directly succeeding iterator of another
given iterator `it` while no value is emitted (see `IterStep.skip`).
-/
@[expose]
def IterM.IsPlausibleSkipSuccessorOf {α : Type w} {m : Type w → Type w'} {β : Type w}
[Iterator α m β] (it' it : IterM (α := α) m β) : Prop :=
it.IsPlausibleStep (.skip it')
@ -356,6 +367,7 @@ section Pure
Asserts that certain step is plausibly the successor of a given iterator. What "plausible" means
is up to the `Iterator` instance but it should be strong enough to allow termination proofs.
-/
@[expose]
def Iter.IsPlausibleStep {α : Type w} {β : Type w} [Iterator α Id β]
(it : Iter (α := α) β) (step : IterStep (Iter (α := α) β) β) : Prop :=
it.toIterM.IsPlausibleStep (step.mapIterator Iter.toIterM)
@ -364,6 +376,7 @@ def Iter.IsPlausibleStep {α : Type w} {β : Type w} [Iterator α Id β]
The type of the step object returned by `Iter.step`, containing an `IterStep`
and a proof that this is a plausible step for the given iterator.
-/
@[expose]
def Iter.Step {α : Type w} {β : Type w} [Iterator α Id β] (it : Iter (α := α) β) :=
PlausibleIterStep (Iter.IsPlausibleStep it)
@ -378,7 +391,7 @@ def Iter.Step.toMonadic {α : Type w} {β : Type w} [Iterator α Id β] {it : It
/--
Converts an `IterM.Step` into an `Iter.Step`.
-/
@[always_inline, inline]
@[always_inline, inline, expose]
def IterM.Step.toPure {α : Type w} {β : Type w} [Iterator α Id β] {it : IterM (α := α) Id β}
(step : it.Step) : it.toIter.Step :=
⟨step.val.mapIterator IterM.toIter, (by simp [Iter.IsPlausibleStep, step.property])⟩
@ -402,6 +415,7 @@ theorem IterM.Step.toPure_done {α β : Type w} [Iterator α Id β] {it : IterM
Asserts that a certain output value could plausibly be emitted by the given iterator in its next
step.
-/
@[expose]
def Iter.IsPlausibleOutput {α : Type w} {β : Type w} [Iterator α Id β]
(it : Iter (α := α) β) (out : β) : Prop :=
it.toIterM.IsPlausibleOutput out
@ -410,6 +424,7 @@ def Iter.IsPlausibleOutput {α : Type w} {β : Type w} [Iterator α Id β]
Asserts that a certain iterator `it'` could plausibly be the directly succeeding iterator of another
given iterator `it`.
-/
@[expose]
def Iter.IsPlausibleSuccessorOf {α : Type w} {β : Type w} [Iterator α Id β]
(it' it : Iter (α := α) β) : Prop :=
it'.toIterM.IsPlausibleSuccessorOf it.toIterM
@ -427,7 +442,7 @@ Makes a single step with the given iterator `it`, potentially emitting a value a
succeeding iterator. If this function is used recursively, termination can sometimes be proved with
the termination measures `it.finitelyManySteps` and `it.finitelyManySkips`.
-/
@[always_inline, inline]
@[always_inline, inline, expose]
def Iter.step {α β : Type w} [Iterator α Id β] (it : Iter (α := α) β) : it.Step :=
it.toIterM.step.run.toPure
@ -456,6 +471,7 @@ structure IterM.TerminationMeasures.Finite
The relation of plausible successors on `IterM.TerminationMeasures.Finite`. It is well-founded
if there is a `Finite` instance.
-/
@[expose]
def IterM.TerminationMeasures.Finite.Rel
{α : Type w} {m : Type w → Type w'} {β : Type w} [Iterator α m β] :
TerminationMeasures.Finite α m → TerminationMeasures.Finite α m → Prop :=
@ -464,12 +480,13 @@ def IterM.TerminationMeasures.Finite.Rel
instance {α : Type w} {m : Type w → Type w'} {β : Type w} [Iterator α m β]
[Finite α m] : WellFoundedRelation (IterM.TerminationMeasures.Finite α m) where
rel := IterM.TerminationMeasures.Finite.Rel
wf := (InvImage.wf _ Finite.wf).transGen
wf := by exact (InvImage.wf _ Finite.wf).transGen
/--
Termination measure to be used in well-founded recursive functions recursing over a finite iterator
(see also `Finite`).
-/
@[expose]
def IterM.finitelyManySteps {α : Type w} {m : Type w → Type w'} {β : Type w} [Iterator α m β]
[Finite α m] (it : IterM (α := α) m β) : IterM.TerminationMeasures.Finite α m :=
⟨it⟩
@ -494,9 +511,10 @@ theorem IterM.TerminationMeasures.Finite.rel_of_skip
macro_rules | `(tactic| decreasing_trivial) => `(tactic|
first
| exact IterM.TerminationMeasures.Finite.rel_of_yield _
| exact IterM.TerminationMeasures.Finite.rel_of_skip _)
| exact IterM.TerminationMeasures.Finite.rel_of_skip _
| fail)
@[inherit_doc IterM.finitelyManySteps]
@[inherit_doc IterM.finitelyManySteps, expose]
def Iter.finitelyManySteps {α : Type w} {β : Type w} [Iterator α Id β] [Finite α Id]
(it : Iter (α := α) β) : IterM.TerminationMeasures.Finite α Id :=
it.toIterM.finitelyManySteps
@ -521,7 +539,8 @@ theorem Iter.TerminationMeasures.Finite.rel_of_skip
macro_rules | `(tactic| decreasing_trivial) => `(tactic|
first
| exact Iter.TerminationMeasures.Finite.rel_of_yield _
| exact Iter.TerminationMeasures.Finite.rel_of_skip _)
| exact Iter.TerminationMeasures.Finite.rel_of_skip _
| fail)
theorem IterM.isPlausibleSuccessorOf_of_yield
{α : Type w} {m : Type w → Type w'} {β : Type w} [Iterator α m β]
@ -561,6 +580,7 @@ structure IterM.TerminationMeasures.Productive
The relation of plausible successors while skipping on `IterM.TerminationMeasures.Productive`.
It is well-founded if there is a `Productive` instance.
-/
@[expose]
def IterM.TerminationMeasures.Productive.Rel
{α : Type w} {m : Type w → Type w'} {β : Type w} [Iterator α m β] :
TerminationMeasures.Productive α m → TerminationMeasures.Productive α m → Prop :=
@ -569,12 +589,13 @@ def IterM.TerminationMeasures.Productive.Rel
instance {α : Type w} {m : Type w → Type w'} {β : Type w} [Iterator α m β]
[Productive α m] : WellFoundedRelation (IterM.TerminationMeasures.Productive α m) where
rel := IterM.TerminationMeasures.Productive.Rel
wf := (InvImage.wf _ Productive.wf).transGen
wf := by exact (InvImage.wf _ Productive.wf).transGen
/--
Termination measure to be used in well-founded recursive functions recursing over a productive
iterator (see also `Productive`).
-/
@[expose]
def IterM.finitelyManySkips {α : Type w} {m : Type w → Type w'} {β : Type w} [Iterator α m β]
[Productive α m] (it : IterM (α := α) m β) : IterM.TerminationMeasures.Productive α m :=
⟨it⟩
@ -590,9 +611,11 @@ theorem IterM.TerminationMeasures.Productive.rel_of_skip
.single h
macro_rules | `(tactic| decreasing_trivial) => `(tactic|
exact IterM.TerminationMeasures.Productive.rel_of_skip _)
first
| exact IterM.TerminationMeasures.Productive.rel_of_skip _
| fail)
@[inherit_doc IterM.finitelyManySkips]
@[inherit_doc IterM.finitelyManySkips, expose]
def Iter.finitelyManySkips {α : Type w} {β : Type w} [Iterator α Id β] [Productive α Id]
(it : Iter (α := α) β) : IterM.TerminationMeasures.Productive α Id :=
it.toIterM.finitelyManySkips
@ -608,7 +631,9 @@ theorem Iter.TerminationMeasures.Productive.rel_of_skip
IterM.TerminationMeasures.Productive.rel_of_skip h
macro_rules | `(tactic| decreasing_trivial) => `(tactic|
exact Iter.TerminationMeasures.Productive.rel_of_skip _)
first
| exact Iter.TerminationMeasures.Productive.rel_of_skip _
| fail)
instance [Iterator α m β] [Finite α m] : Productive α m where
wf := by

View file

@ -0,0 +1,13 @@
/-
Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Paul Reichert
-/
module
prelude
import Init.Data.Iterators.Consumers.Monadic
import Init.Data.Iterators.Consumers.Access
import Init.Data.Iterators.Consumers.Collect
import Init.Data.Iterators.Consumers.Loop
import Init.Data.Iterators.Consumers.Partial

View file

@ -3,8 +3,10 @@ Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Paul Reichert
-/
module
prelude
import Std.Data.Iterators.Consumers.Partial
import Init.Data.Iterators.Consumers.Partial
namespace Std.Iterators

View file

@ -3,10 +3,12 @@ Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Paul Reichert
-/
module
prelude
import Std.Data.Iterators.Basic
import Std.Data.Iterators.Consumers.Partial
import Std.Data.Iterators.Consumers.Monadic.Collect
import Init.Data.Iterators.Basic
import Init.Data.Iterators.Consumers.Partial
import Init.Data.Iterators.Consumers.Monadic.Collect
/-!
# Collectors

View file

@ -3,9 +3,11 @@ Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Paul Reichert
-/
module
prelude
import Std.Data.Iterators.Consumers.Monadic.Loop
import Std.Data.Iterators.Consumers.Partial
import Init.Data.Iterators.Consumers.Monadic.Loop
import Init.Data.Iterators.Consumers.Partial
/-!
# Loop consumers

View file

@ -0,0 +1,11 @@
/-
Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Paul Reichert
-/
module
prelude
import Init.Data.Iterators.Consumers.Monadic.Collect
import Init.Data.Iterators.Consumers.Monadic.Loop
import Init.Data.Iterators.Consumers.Monadic.Partial

View file

@ -3,9 +3,11 @@ Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Paul Reichert
-/
module
prelude
import Std.Data.Iterators.Consumers.Monadic.Partial
import Std.Data.Internal.LawfulMonadLiftFunction
import Init.Data.Iterators.Consumers.Monadic.Partial
import Init.Data.Iterators.Internal.LawfulMonadLiftFunction
/-!
# Collectors

View file

@ -3,10 +3,12 @@ Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Paul Reichert
-/
module
prelude
import Init.RCases
import Std.Data.Iterators.Basic
import Std.Data.Iterators.Consumers.Monadic.Partial
import Init.Data.Iterators.Basic
import Init.Data.Iterators.Consumers.Monadic.Partial
/-!
# Loop-based consumers
@ -62,8 +64,9 @@ class IteratorLoop (α : Type w) (m : Type w → Type w') {β : Type w} [Iterato
forIn : ∀ (_lift : (γ : Type w) → m γ → n γ) (γ : Type w),
(plausible_forInStep : β → γ → ForInStep γ → Prop) →
IteratorLoop.WellFounded α m plausible_forInStep →
IterM (α := α) m β → γ
((b : β) → (c : γ) → n (Subtype (plausible_forInStep b c))) → n γ
(it : IterM (α := α) m β) → γ
((b : β) → (c : γ) → n (Subtype (plausible_forInStep b c))) →
n γ
/--
`IteratorLoopPartial α m` provides efficient implementations of loop-based consumers for `α`-based
@ -76,7 +79,8 @@ provided by the standard library.
class IteratorLoopPartial (α : Type w) (m : Type w → Type w') {β : Type w} [Iterator α m β]
(n : Type w → Type w'') where
forInPartial : ∀ (_lift : (γ : Type w) → m γ → n γ) {γ : Type w},
IterM (α := α) m β → γ → ((b : β) → (c : γ) → n (ForInStep γ)) → n γ
(it : IterM (α := α) m β) → γ
((b : β) → (c : γ) → n (ForInStep γ)) → n γ
end Typeclasses
@ -91,7 +95,7 @@ private def IteratorLoop.WFRel.mk {α : Type w} {m : Type w → Type w'} {β : T
IteratorLoop.WFRel wf :=
(it, c)
instance {α : Type w} {m : Type w → Type w'} {β : Type w} [Iterator α m β]
private instance {α : Type w} {m : Type w → Type w'} {β : Type w} [Iterator α m β]
{γ : Type x} {plausible_forInStep : β → γ → ForInStep γ → Prop}
(wf : IteratorLoop.WellFounded α m plausible_forInStep) :
WellFoundedRelation (IteratorLoop.WFRel wf) where
@ -116,9 +120,13 @@ def IterM.DefaultConsumers.forIn {m : Type w → Type w'} {α : Type w} {β : Ty
match ← it.step with
| .yield it' out _ =>
match ← f out init with
| ⟨.yield c, _⟩ => IterM.DefaultConsumers.forIn lift _ plausible_forInStep wf it' c f
| ⟨.yield c, _⟩ =>
IterM.DefaultConsumers.forIn lift _ plausible_forInStep wf it' c
(fun out acc => f out acc)
| ⟨.done c, _⟩ => return c
| .skip it' _ => IterM.DefaultConsumers.forIn lift _ plausible_forInStep wf it' init f
| .skip it' _ =>
IterM.DefaultConsumers.forIn lift _ plausible_forInStep wf it' init
(fun out acc => f out acc)
| .done _ => return init
termination_by IteratorLoop.WFRel.mk wf it init
decreasing_by
@ -159,9 +167,13 @@ partial def IterM.DefaultConsumers.forInPartial {m : Type w → Type w'} {α : T
match ← it.step with
| .yield it' out _ =>
match ← f out init with
| .yield c => IterM.DefaultConsumers.forInPartial lift _ it' c f
| .yield c =>
IterM.DefaultConsumers.forInPartial lift _ it' c
fun out acc => f out acc
| .done c => return c
| .skip it' _ => IterM.DefaultConsumers.forInPartial lift _ it' init f
| .skip it' _ =>
IterM.DefaultConsumers.forInPartial lift _ it' init
fun out acc => f out acc
| .done _ => return init
/--
@ -206,12 +218,13 @@ def IteratorLoop.finiteForIn {m : Type w → Type w'} {n : Type w → Type w''}
forIn {γ} [Monad n] it init f :=
IteratorLoop.forIn (α := α) (m := m) lift γ (fun _ _ _ => True)
wellFounded_of_finite
it init ((⟨·, .intro⟩) <$> f · ·)
it init (fun out acc => (⟨·, .intro⟩) <$> f out acc)
instance {m : Type w → Type w'} {n : Type w → Type w''}
{α : Type w} {β : Type w} [Iterator α m β] [Finite α m] [IteratorLoop α m n]
[MonadLiftT m n] :
ForIn n (IterM (α := α) m β) β := IteratorLoop.finiteForIn (fun _ => monadLift)
ForIn n (IterM (α := α) m β) β :=
IteratorLoop.finiteForIn (fun _ => monadLift)
instance {m : Type w → Type w'} {n : Type w → Type w''}
{α : Type w} {β : Type w} [Iterator α m β] [IteratorLoopPartial α m n] [MonadLiftT m n] :

View file

@ -3,8 +3,10 @@ Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Paul Reichert
-/
module
prelude
import Std.Data.Iterators.Basic
import Init.Data.Iterators.Basic
namespace Std.Iterators

View file

@ -3,8 +3,10 @@ Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Paul Reichert
-/
module
prelude
import Std.Data.Iterators.Basic
import Init.Data.Iterators.Basic
namespace Std.Iterators

View file

@ -0,0 +1,10 @@
/-
Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Paul Reichert
-/
module
prelude
import Init.Data.Iterators.Internal.LawfulMonadLiftFunction
import Init.Data.Iterators.Internal.Termination

View file

@ -3,6 +3,8 @@ Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Paul Reichert
-/
module
prelude
import Init.Control.Basic
import Init.Control.Lawful.Basic

View file

@ -3,8 +3,10 @@ Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Paul Reichert
-/
module
prelude
import Std.Data.Iterators.Basic
import Init.Data.Iterators.Basic
/-!
This is an internal module used by iterator implementations.

View file

@ -3,5 +3,7 @@ Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Paul Reichert
-/
module
prelude
import Std.Data.Iterators.Internal.Termination
import Init.Data.Iterators.Lemmas.Consumers

View file

@ -3,8 +3,10 @@ Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Paul Reichert
-/
module
prelude
import Std.Data.Iterators.Basic
import Init.Data.Iterators.Basic
namespace Std.Iterators

View file

@ -0,0 +1,11 @@
/-
Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Paul Reichert
-/
module
prelude
import Init.Data.Iterators.Lemmas.Consumers.Monadic
import Init.Data.Iterators.Lemmas.Consumers.Collect
import Init.Data.Iterators.Lemmas.Consumers.Loop

View file

@ -0,0 +1,114 @@
/-
Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Paul Reichert
-/
module
prelude
import Init.Data.Iterators.Lemmas.Basic
import Init.Data.Iterators.Lemmas.Consumers.Monadic.Collect
import all Init.Data.Iterators.Consumers.Access
import all Init.Data.Iterators.Consumers.Collect
namespace Std.Iterators
theorem Iter.toArray_eq_toArray_toIterM {α β} [Iterator α Id β] [Finite α Id] [IteratorCollect α Id Id]
[LawfulIteratorCollect α Id Id] {it : Iter (α := α) β} :
it.toArray = it.toIterM.toArray.run :=
(rfl)
theorem Iter.toList_eq_toList_toIterM {α β} [Iterator α Id β] [Finite α Id] [IteratorCollect α Id Id]
[LawfulIteratorCollect α Id Id] {it : Iter (α := α) β} :
it.toList = it.toIterM.toList.run :=
(rfl)
theorem Iter.toListRev_eq_toListRev_toIterM {α β} [Iterator α Id β] [Finite α Id]
{it : Iter (α := α) β} :
it.toListRev = it.toIterM.toListRev.run :=
(rfl)
@[simp]
theorem IterM.toList_toIter {α β} [Iterator α Id β] [Finite α Id] [IteratorCollect α Id Id]
{it : IterM (α := α) Id β} :
it.toIter.toList = it.toList.run :=
(rfl)
@[simp]
theorem IterM.toListRev_toIter {α β} [Iterator α Id β] [Finite α Id]
{it : IterM (α := α) Id β} :
it.toIter.toListRev = it.toListRev.run :=
(rfl)
theorem Iter.toList_toArray {α β} [Iterator α Id β] [Finite α Id] [IteratorCollect α Id Id]
[LawfulIteratorCollect α Id Id] {it : Iter (α := α) β} :
it.toArray.toList = it.toList := by
simp [toArray_eq_toArray_toIterM, toList_eq_toList_toIterM, ← IterM.toList_toArray]
theorem Iter.toArray_toList {α β} [Iterator α Id β] [Finite α Id] [IteratorCollect α Id Id]
[LawfulIteratorCollect α Id Id] {it : Iter (α := α) β} :
it.toList.toArray = it.toArray := by
simp [toArray_eq_toArray_toIterM, toList_eq_toList_toIterM, ← IterM.toArray_toList]
@[simp]
theorem Iter.reverse_toListRev [Iterator α Id β] [Finite α Id]
[IteratorCollect α Id Id] [LawfulIteratorCollect α Id Id]
{it : Iter (α := α) β} :
it.toListRev.reverse = it.toList := by
simp [toListRev_eq_toListRev_toIterM, toList_eq_toList_toIterM, ← IterM.reverse_toListRev]
theorem Iter.toListRev_eq {α β} [Iterator α Id β] [Finite α Id] [IteratorCollect α Id Id]
[LawfulIteratorCollect α Id Id] {it : Iter (α := α) β} :
it.toListRev = it.toList.reverse := by
simp [Iter.toListRev_eq_toListRev_toIterM, Iter.toList_eq_toList_toIterM, IterM.toListRev_eq]
theorem Iter.toArray_eq_match_step {α β} [Iterator α Id β] [Finite α Id] [IteratorCollect α Id Id]
[LawfulIteratorCollect α Id Id] {it : Iter (α := α) β} :
it.toArray = match it.step with
| .yield it' out _ => #[out] ++ it'.toArray
| .skip it' _ => it'.toArray
| .done _ => #[] := by
simp only [Iter.toArray_eq_toArray_toIterM, Iter.step]
rw [IterM.toArray_eq_match_step, Id.run_bind]
generalize it.toIterM.step.run = step
cases step using PlausibleIterStep.casesOn <;> simp
theorem Iter.toList_eq_match_step {α β} [Iterator α Id β] [Finite α Id] [IteratorCollect α Id Id]
[LawfulIteratorCollect α Id Id] {it : Iter (α := α) β} :
it.toList = match it.step with
| .yield it' out _ => out :: it'.toList
| .skip it' _ => it'.toList
| .done _ => [] := by
rw [← Iter.toList_toArray, Iter.toArray_eq_match_step]
split <;> simp [Iter.toList_toArray]
theorem Iter.toListRev_eq_match_step {α β} [Iterator α Id β] [Finite α Id] {it : Iter (α := α) β} :
it.toListRev = match it.step with
| .yield it' out _ => it'.toListRev ++ [out]
| .skip it' _ => it'.toListRev
| .done _ => [] := by
rw [Iter.toListRev_eq_toListRev_toIterM, IterM.toListRev_eq_match_step, Iter.step, Id.run_bind]
generalize it.toIterM.step.run = step
cases step using PlausibleIterStep.casesOn <;> simp
theorem Iter.getElem?_toList_eq_atIdxSlow? {α β}
[Iterator α Id β] [Finite α Id] [IteratorCollect α Id Id] [LawfulIteratorCollect α Id Id]
{it : Iter (α := α) β} {k : Nat} :
it.toList[k]? = it.atIdxSlow? k := by
induction it using Iter.inductSteps generalizing k with | step it ihy ihs =>
rw [toList_eq_match_step, atIdxSlow?]
obtain ⟨step, h⟩ := it.step
cases step
· cases k <;> simp [ihy h]
· simp [ihs h]
· simp
theorem Iter.toList_eq_of_atIdxSlow?_eq {α₁ α₂ β}
[Iterator α₁ Id β] [Finite α₁ Id] [IteratorCollect α₁ Id Id] [LawfulIteratorCollect α₁ Id Id]
[Iterator α₂ Id β] [Finite α₂ Id] [IteratorCollect α₂ Id Id] [LawfulIteratorCollect α₂ Id Id]
{it₁ : Iter (α := α₁) β} {it₂ : Iter (α := α₂) β}
(h : ∀ k, it₁.atIdxSlow? k = it₂.atIdxSlow? k) :
it₁.toList = it₂.toList := by
ext; simp [getElem?_toList_eq_atIdxSlow?, h]
end Std.Iterators

View file

@ -0,0 +1,180 @@
/-
Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Paul Reichert
-/
module
prelude
import Init.Data.Iterators.Lemmas.Consumers.Collect
import all Init.Data.Iterators.Lemmas.Consumers.Monadic.Loop
import all Init.Data.Iterators.Consumers.Loop
namespace Std.Iterators
theorem Iter.forIn_eq {α β : Type w} [Iterator α Id β] [Finite α Id]
{m : Type w → Type w''} [Monad m] [IteratorLoop α Id m] [hl : LawfulIteratorLoop α Id m]
{γ : Type w} {it : Iter (α := α) β} {init : γ}
{f : (b : β) → γ → m (ForInStep γ)} :
ForIn.forIn it init f =
IterM.DefaultConsumers.forIn (fun _ c => pure c.run) γ (fun _ _ _ => True)
IteratorLoop.wellFounded_of_finite it.toIterM init
(fun out acc => (⟨·, .intro⟩) <$>
f out acc) := by
cases hl.lawful; rfl
theorem Iter.forIn_eq_forIn_toIterM {α β : Type w} [Iterator α Id β]
[Finite α Id] {m : Type w → Type w''} [Monad m] [LawfulMonad m]
[IteratorLoop α Id m] [LawfulIteratorLoop α Id m]
{γ : Type w} {it : Iter (α := α) β} {init : γ}
{f : β → γ → m (ForInStep γ)} :
ForIn.forIn it init f =
letI : MonadLift Id m := ⟨Std.Internal.idToMonad (α := _)⟩
ForIn.forIn it.toIterM init f := by
rfl
theorem Iter.forIn_eq_match_step {α β : Type w} [Iterator α Id β]
[Finite α Id] {m : Type w → Type w''} [Monad m] [LawfulMonad m]
[IteratorLoop α Id m] [LawfulIteratorLoop α Id m]
{γ : Type w} {it : Iter (α := α) β} {init : γ}
{f : β → γ → m (ForInStep γ)} :
ForIn.forIn it init f = (do
match it.step with
| .yield it' out _ =>
match ← f out init with
| .yield c => ForIn.forIn it' c f
| .done c => return c
| .skip it' _ => ForIn.forIn it' init f
| .done _ => return init) := by
rw [Iter.forIn_eq_forIn_toIterM, @IterM.forIn_eq_match_step, Iter.step]
simp only [liftM, monadLift, pure_bind]
generalize it.toIterM.step = step
cases step using PlausibleIterStep.casesOn
· apply bind_congr
intro forInStep
rfl
· rfl
· rfl
theorem Iter.forIn_toList {α β : Type w} [Iterator α Id β]
[Finite α Id] {m : Type w → Type w''} [Monad m] [LawfulMonad m]
[IteratorLoop α Id m] [LawfulIteratorLoop α Id m]
[IteratorCollect α Id Id] [LawfulIteratorCollect α Id Id]
{γ : Type w} {it : Iter (α := α) β} {init : γ}
{f : β → γ → m (ForInStep γ)} :
ForIn.forIn it.toList init f = ForIn.forIn it init f := by
rw [List.forIn_eq_foldlM]
induction it using Iter.inductSteps generalizing init with case step it ihy ihs =>
rw [forIn_eq_match_step, Iter.toList_eq_match_step]
simp only [map_eq_pure_bind]
generalize it.step = step
cases step using PlausibleIterStep.casesOn
· rename_i it' out h
simp only [List.foldlM_cons, bind_pure_comp, map_bind]
apply bind_congr
intro forInStep
cases forInStep
· induction it'.toList <;> simp [*]
· simp only [ForIn.forIn, forIn', List.forIn'] at ihy
simp [ihy h, forIn_eq_forIn_toIterM]
· rename_i it' h
simp only [bind_pure_comp]
rw [ihs h]
· simp
theorem Iter.foldM_eq_forIn {α β γ : Type w} [Iterator α Id β] [Finite α Id] {m : Type w → Type w'}
[Monad m] [IteratorLoop α Id m] {f : γ → β → m γ}
{init : γ} {it : Iter (α := α) β} :
it.foldM (init := init) f = ForIn.forIn it init (fun x acc => ForInStep.yield <$> f acc x) :=
(rfl)
theorem Iter.foldM_eq_foldM_toIterM {α β : Type w} [Iterator α Id β]
[Finite α Id] {m : Type w → Type w''} [Monad m] [LawfulMonad m]
[IteratorLoop α Id m] [LawfulIteratorLoop α Id m]
{γ : Type w} {it : Iter (α := α) β} {init : γ} {f : γ → β → m γ} :
it.foldM (init := init) f = letI : MonadLift Id m := ⟨pure⟩; it.toIterM.foldM (init := init) f :=
(rfl)
theorem Iter.forIn_yield_eq_foldM {α β γ δ : Type w} [Iterator α Id β]
[Finite α Id] {m : Type w → Type w''} [Monad m] [LawfulMonad m] [IteratorLoop α Id m]
[LawfulIteratorLoop α Id m] {f : β → γ → m δ} {g : β → γ → δ → γ} {init : γ}
{it : Iter (α := α) β} :
ForIn.forIn it init (fun c b => (fun d => .yield (g c b d)) <$> f c b) =
it.foldM (fun b c => g c b <$> f c b) init := by
simp [Iter.foldM_eq_forIn]
theorem Iter.foldM_eq_match_step {α β γ : Type w} [Iterator α Id β] [Finite α Id]
{m : Type w → Type w'} [Monad m] [LawfulMonad m] [IteratorLoop α Id m]
[LawfulIteratorLoop α Id m] {f : γ → β → m γ} {init : γ} {it : Iter (α := α) β} :
it.foldM (init := init) f = (do
match it.step with
| .yield it' out _ => it'.foldM (init := ← f init out) f
| .skip it' _ => it'.foldM (init := init) f
| .done _ => return init) := by
rw [Iter.foldM_eq_forIn, Iter.forIn_eq_match_step]
generalize it.step = step
cases step using PlausibleIterStep.casesOn <;> simp [foldM_eq_forIn]
theorem Iter.foldlM_toList {α β γ : Type w} [Iterator α Id β] [Finite α Id] {m : Type w → Type w'}
[Monad m] [LawfulMonad m] [IteratorLoop α Id m] [LawfulIteratorLoop α Id m]
[IteratorCollect α Id Id] [LawfulIteratorCollect α Id Id]
{f : γ → β → m γ}
{init : γ} {it : Iter (α := α) β} :
it.toList.foldlM (init := init) f = it.foldM (init := init) f := by
rw [Iter.foldM_eq_forIn, ← Iter.forIn_toList]
simp only [List.forIn_yield_eq_foldlM, id_map']
theorem IterM.forIn_eq_foldM {α β : Type w} [Iterator α Id β]
[Finite α Id] {m : Type w → Type w''} [Monad m] [LawfulMonad m]
[IteratorLoop α Id m] [LawfulIteratorLoop α Id m]
[IteratorCollect α Id Id] [LawfulIteratorCollect α Id Id]
{γ : Type w} {it : Iter (α := α) β} {init : γ}
{f : β → γ → m (ForInStep γ)} :
forIn it init f = ForInStep.value <$>
it.foldM (fun c b => match c with
| .yield c => f b c
| .done c => pure (.done c)) (ForInStep.yield init) := by
simp only [← Iter.forIn_toList, List.forIn_eq_foldlM, ← Iter.foldlM_toList]; rfl
theorem Iter.fold_eq_forIn {α β γ : Type w} [Iterator α Id β]
[Finite α Id] [IteratorLoop α Id Id] {f : γ → β → γ} {init : γ} {it : Iter (α := α) β} :
it.fold (init := init) f =
(ForIn.forIn (m := Id) it init (fun x acc => pure (ForInStep.yield (f acc x)))).run := by
rfl
theorem Iter.fold_eq_foldM {α β γ : Type w} [Iterator α Id β]
[Finite α Id] [IteratorLoop α Id Id] {f : γ → β → γ} {init : γ}
{it : Iter (α := α) β} :
it.fold (init := init) f = (it.foldM (m := Id) (init := init) (pure <| f · ·)).run := by
simp [foldM_eq_forIn, fold_eq_forIn]
@[simp]
theorem Iter.forIn_pure_yield_eq_fold {α β γ : Type w} [Iterator α Id β]
[Finite α Id] [IteratorLoop α Id Id]
[LawfulIteratorLoop α Id Id] {f : β → γγ} {init : γ}
{it : Iter (α := α) β} :
ForIn.forIn (m := Id) it init (fun c b => pure (.yield (f c b))) =
pure (it.fold (fun b c => f c b) init) := by
simp only [fold_eq_forIn]
rfl
theorem Iter.fold_eq_match_step {α β γ : Type w} [Iterator α Id β] [Finite α Id]
[IteratorLoop α Id Id] [LawfulIteratorLoop α Id Id]
{f : γ → β → γ} {init : γ} {it : Iter (α := α) β} :
it.fold (init := init) f = (match it.step with
| .yield it' out _ => it'.fold (init := f init out) f
| .skip it' _ => it'.fold (init := init) f
| .done _ => init) := by
rw [fold_eq_foldM, foldM_eq_match_step]
simp only [fold_eq_foldM]
generalize it.step = step
cases step using PlausibleIterStep.casesOn <;> simp
theorem Iter.foldl_toList {α β γ : Type w} [Iterator α Id β] [Finite α Id]
[IteratorLoop α Id Id] [LawfulIteratorLoop α Id Id]
[IteratorCollect α Id Id] [LawfulIteratorCollect α Id Id]
{f : γ → β → γ} {init : γ} {it : Iter (α := α) β} :
it.toList.foldl (init := init) f = it.fold (init := init) f := by
rw [fold_eq_foldM, List.foldl_eq_foldlM, ← Iter.foldlM_toList]
end Std.Iterators

View file

@ -3,7 +3,8 @@ Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Paul Reichert
-/
module
prelude
import Std.Data.Iterators.Consumers.Monadic.Collect
import Std.Data.Iterators.Consumers.Monadic.Loop
import Std.Data.Iterators.Consumers.Monadic.Partial
import Init.Data.Iterators.Lemmas.Consumers.Monadic.Collect
import Init.Data.Iterators.Lemmas.Consumers.Monadic.Loop

View file

@ -0,0 +1,157 @@
/-
Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Paul Reichert
-/
module
prelude
import Init.Data.Array.Lemmas
import Init.Data.Iterators.Lemmas.Monadic.Basic
import all Init.Data.Iterators.Consumers.Monadic.Collect
namespace Std.Iterators
variable {α β γ : Type w} {m : Type w → Type w'} {n : Type w → Type w''}
{lift : ⦃δ : Type w⦄ → m δ → n δ} {f : β → n γ} {it : IterM (α := α) m β}
theorem IterM.DefaultConsumers.toArrayMapped.go.aux₁ [Monad n] [LawfulMonad n] [Iterator α m β]
[Finite α m] {b : γ} {bs : Array γ} :
IterM.DefaultConsumers.toArrayMapped.go lift f it (#[b] ++ bs) (m := m) =
(#[b] ++ ·) <$> IterM.DefaultConsumers.toArrayMapped.go lift f it bs (m := m) := by
induction it, bs using IterM.DefaultConsumers.toArrayMapped.go.induct
next it bs ih₁ ih₂ =>
rw [go, map_eq_pure_bind, go, bind_assoc]
apply bind_congr
intro step
split
· simp [ih₁ _ _ _]
· simp [ih₂ _ _]
· simp
theorem IterM.DefaultConsumers.toArrayMapped.go.aux₂ [Monad n] [LawfulMonad n] [Iterator α m β]
[Finite α m] {acc : Array γ} :
IterM.DefaultConsumers.toArrayMapped.go lift f it acc (m := m) =
(acc ++ ·) <$> IterM.DefaultConsumers.toArrayMapped lift f it (m := m) := by
rw [← Array.toArray_toList (xs := acc)]
generalize acc.toList = acc
induction acc with
| nil => simp [toArrayMapped]
| cons x xs ih =>
rw [List.toArray_cons, IterM.DefaultConsumers.toArrayMapped.go.aux₁, ih]
simp only [Functor.map_map, Array.append_assoc]
theorem IterM.DefaultConsumers.toArrayMapped_eq_match_step [Monad n] [LawfulMonad n]
[Iterator α m β] [Finite α m] :
IterM.DefaultConsumers.toArrayMapped lift f it (m := m) = letI : MonadLift m n := ⟨lift (δ := _)⟩; (do
match ← it.step with
| .yield it' out _ =>
return #[← f out] ++ (← IterM.DefaultConsumers.toArrayMapped lift f it' (m := m))
| .skip it' _ => IterM.DefaultConsumers.toArrayMapped lift f it' (m := m)
| .done _ => return #[]) := by
rw [IterM.DefaultConsumers.toArrayMapped, IterM.DefaultConsumers.toArrayMapped.go]
apply bind_congr
intro step
split <;> simp [IterM.DefaultConsumers.toArrayMapped.go.aux₂]
theorem IterM.toArray_eq_match_step [Monad m] [LawfulMonad m] [Iterator α m β] [Finite α m]
[IteratorCollect α m m] [LawfulIteratorCollect α m m] :
it.toArray = (do
match ← it.step with
| .yield it' out _ => return #[out] ++ (← it'.toArray)
| .skip it' _ => it'.toArray
| .done _ => return #[]) := by
simp only [IterM.toArray, LawfulIteratorCollect.toArrayMapped_eq]
rw [IterM.DefaultConsumers.toArrayMapped_eq_match_step]
simp [bind_pure_comp, pure_bind, toArray]
theorem IterM.toList_toArray [Monad m] [Iterator α m β] [Finite α m] [IteratorCollect α m m]
{it : IterM (α := α) m β} :
Array.toList <$> it.toArray = it.toList := by
simp [IterM.toList]
theorem IterM.toArray_toList [Monad m] [LawfulMonad m] [Iterator α m β] [Finite α m]
[IteratorCollect α m m] {it : IterM (α := α) m β} :
List.toArray <$> it.toList = it.toArray := by
simp [IterM.toList]
theorem IterM.toList_eq_match_step [Monad m] [LawfulMonad m] [Iterator α m β] [Finite α m]
[IteratorCollect α m m] [LawfulIteratorCollect α m m] {it : IterM (α := α) m β} :
it.toList = (do
match ← it.step with
| .yield it' out _ => return out :: (← it'.toList)
| .skip it' _ => it'.toList
| .done _ => return []) := by
simp [← IterM.toList_toArray]
rw [IterM.toArray_eq_match_step, map_eq_pure_bind, bind_assoc]
apply bind_congr
intro step
split <;> simp
theorem IterM.toListRev.go.aux₁ [Monad m] [LawfulMonad m] [Iterator α m β] [Finite α m]
{it : IterM (α := α) m β} {b : β} {bs : List β} :
IterM.toListRev.go it (bs ++ [b]) = (· ++ [b]) <$> IterM.toListRev.go it bs:= by
induction it, bs using IterM.toListRev.go.induct
next it bs ih₁ ih₂ =>
rw [go, go, map_eq_pure_bind, bind_assoc]
apply bind_congr
intro step
simp only [List.cons_append] at ih₁
split <;> simp [*]
theorem IterM.toListRev.go.aux₂ [Monad m] [LawfulMonad m] [Iterator α m β] [Finite α m]
{it : IterM (α := α) m β} {acc : List β} :
IterM.toListRev.go it acc = (· ++ acc) <$> it.toListRev := by
rw [← List.reverse_reverse (as := acc)]
generalize acc.reverse = acc
induction acc with
| nil => simp [toListRev]
| cons x xs ih => simp [IterM.toListRev.go.aux₁, ih]
theorem IterM.toListRev_eq_match_step [Monad m] [LawfulMonad m] [Iterator α m β] [Finite α m]
{it : IterM (α := α) m β} :
it.toListRev = (do
match ← it.step with
| .yield it' out _ => return (← it'.toListRev) ++ [out]
| .skip it' _ => it'.toListRev
| .done _ => return []) := by
simp [IterM.toListRev]
rw [toListRev.go]
apply bind_congr
intro step
cases step using PlausibleIterStep.casesOn <;> simp [IterM.toListRev.go.aux₂]
theorem IterM.reverse_toListRev [Monad m] [LawfulMonad m] [Iterator α m β] [Finite α m]
[IteratorCollect α m m] [LawfulIteratorCollect α m m]
{it : IterM (α := α) m β} :
List.reverse <$> it.toListRev = it.toList := by
apply Eq.symm
induction it using IterM.inductSteps
rename_i it ihy ihs
rw [toListRev_eq_match_step, toList_eq_match_step, map_eq_pure_bind, bind_assoc]
apply bind_congr
intro step
split <;> simp (discharger := assumption) [ihy, ihs]
theorem IterM.toListRev_eq [Monad m] [LawfulMonad m] [Iterator α m β] [Finite α m]
[IteratorCollect α m m] [LawfulIteratorCollect α m m]
{it : IterM (α := α) m β} :
it.toListRev = List.reverse <$> it.toList := by
rw [← IterM.reverse_toListRev]
simp
theorem LawfulIteratorCollect.toArray_eq {α β : Type w} {m : Type w → Type w'}
[Monad m] [Iterator α m β] [Finite α m] [IteratorCollect α m m]
[hl : LawfulIteratorCollect α m m]
{it : IterM (α := α) m β} :
it.toArray = (letI : IteratorCollect α m m := .defaultImplementation; it.toArray) := by
simp only [IterM.toArray, toArrayMapped_eq]
theorem LawfulIteratorCollect.toList_eq {α β : Type w} {m : Type w → Type w'}
[Monad m] [Iterator α m β] [Finite α m] [IteratorCollect α m m]
[hl : LawfulIteratorCollect α m m]
{it : IterM (α := α) m β} :
it.toList = (letI : IteratorCollect α m m := .defaultImplementation; it.toList) := by
simp [IterM.toList, toArray_eq]
end Std.Iterators

View file

@ -0,0 +1,239 @@
/-
Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Paul Reichert
-/
module
prelude
import Init.Data.Iterators.Lemmas.Consumers.Monadic.Collect
import all Init.Data.Iterators.Consumers.Monadic.Loop
namespace Std.Iterators
theorem IterM.DefaultConsumers.forIn_eq_match_step {α β : Type w} {m : Type w → Type w'}
[Iterator α m β]
{n : Type w → Type w''} [Monad n]
{lift : ∀ γ, m γ → n γ} {γ : Type w}
{plausible_forInStep : β → γ → ForInStep γ → Prop}
{wf : IteratorLoop.WellFounded α m plausible_forInStep}
{it : IterM (α := α) m β} {init : γ}
{f : (b : β) → (c : γ) → n (Subtype (plausible_forInStep b c))} :
IterM.DefaultConsumers.forIn lift γ plausible_forInStep wf it init f = (do
match ← lift _ it.step with
| .yield it' out _ =>
match ← f out init with
| ⟨.yield c, _⟩ =>
IterM.DefaultConsumers.forIn lift _ plausible_forInStep wf it' c
fun out acc => f out acc
| ⟨.done c, _⟩ => return c
| .skip it' _ =>
IterM.DefaultConsumers.forIn lift _ plausible_forInStep wf it' init
fun out acc => f out acc
| .done _ => return init) := by
rw [forIn]
apply bind_congr
intro step
cases step using PlausibleIterStep.casesOn <;> rfl
theorem IterM.forIn_eq {α β : Type w} {m : Type w → Type w'} [Iterator α m β] [Finite α m]
{n : Type w → Type w''} [Monad n] [IteratorLoop α m n] [hl : LawfulIteratorLoop α m n]
[MonadLiftT m n] {γ : Type w} {it : IterM (α := α) m β} {init : γ}
{f : β → γ → n (ForInStep γ)} :
ForIn.forIn it init f = IterM.DefaultConsumers.forIn (fun _ => monadLift) γ (fun _ _ _ => True)
IteratorLoop.wellFounded_of_finite it init (fun out acc => (⟨·, .intro⟩) <$> f out acc) := by
cases hl.lawful; rfl
theorem IterM.forIn_eq_match_step {α β : Type w} {m : Type w → Type w'} [Iterator α m β]
[Finite α m] {n : Type w → Type w''} [Monad n] [LawfulMonad n]
[IteratorLoop α m n] [LawfulIteratorLoop α m n]
[MonadLiftT m n] {γ : Type w} {it : IterM (α := α) m β} {init : γ}
{f : β → γ → n (ForInStep γ)} :
ForIn.forIn it init f = (do
match ← it.step with
| .yield it' out _ =>
match ← f out init with
| .yield c => ForIn.forIn it' c f
| .done c => return c
| .skip it' _ => ForIn.forIn it' init f
| .done _ => return init) := by
rw [IterM.forIn_eq, DefaultConsumers.forIn_eq_match_step]
apply bind_congr
intro step
cases step using PlausibleIterStep.casesOn
· simp only [map_eq_pure_bind, bind_assoc]
apply bind_congr
intro forInStep
cases forInStep <;> simp [IterM.forIn_eq]
· simp [IterM.forIn_eq]
· simp
theorem IterM.forM_eq_forIn {α β : Type w} {m : Type w → Type w'} [Iterator α m β]
[Finite α m] {n : Type w → Type w''} [Monad n] [LawfulMonad n]
[IteratorLoop α m n] [LawfulIteratorLoop α m n]
[MonadLiftT m n] {it : IterM (α := α) m β}
{f : β → n PUnit} :
ForM.forM it f = ForIn.forIn it PUnit.unit (fun out _ => do f out; return .yield .unit) :=
rfl
theorem IterM.forM_eq_match_step {α β : Type w} {m : Type w → Type w'} [Iterator α m β]
[Finite α m] {n : Type w → Type w''} [Monad n] [LawfulMonad n]
[IteratorLoop α m n] [LawfulIteratorLoop α m n]
[MonadLiftT m n] {it : IterM (α := α) m β}
{f : β → n PUnit} :
ForM.forM it f = (do
match ← it.step with
| .yield it' out _ =>
f out
ForM.forM it' f
| .skip it' _ => ForM.forM it' f
| .done _ => return) := by
rw [forM_eq_forIn, forIn_eq_match_step]
apply bind_congr
intro step
cases step using PlausibleIterStep.casesOn <;> simp [forM_eq_forIn]
theorem IterM.foldM_eq_forIn {α β γ : Type w} {m : Type w → Type w'} [Iterator α m β] [Finite α m]
{n : Type w → Type w''} [Monad n] [IteratorLoop α m n] [MonadLiftT m n] {f : γ → β → n γ}
{init : γ} {it : IterM (α := α) m β} :
it.foldM (init := init) f = ForIn.forIn it init (fun x acc => ForInStep.yield <$> f acc x) :=
(rfl)
theorem IterM.forIn_yield_eq_foldM {α β γ δ : Type w} {m : Type w → Type w'} [Iterator α m β]
[Finite α m] {n : Type w → Type w''} [Monad n] [LawfulMonad n] [IteratorLoop α m n]
[LawfulIteratorLoop α m n] [MonadLiftT m n] {f : β → γ → n δ} {g : β → γ → δ → γ} {init : γ}
{it : IterM (α := α) m β} :
ForIn.forIn it init (fun c b => (fun d => .yield (g c b d)) <$> f c b) =
it.foldM (fun b c => g c b <$> f c b) init := by
simp [IterM.foldM_eq_forIn]
theorem IterM.foldM_eq_match_step {α β γ : Type w} {m : Type w → Type w'} [Iterator α m β] [Finite α m]
{n : Type w → Type w''} [Monad n] [LawfulMonad n] [IteratorLoop α m n] [LawfulIteratorLoop α m n]
[MonadLiftT m n] {f : γ → β → n γ} {init : γ} {it : IterM (α := α) m β} :
it.foldM (init := init) f = (do
match ← it.step with
| .yield it' out _ => it'.foldM (init := ← f init out) f
| .skip it' _ => it'.foldM (init := init) f
| .done _ => return init) := by
rw [IterM.foldM_eq_forIn, IterM.forIn_eq_match_step]
apply bind_congr
intro step
cases step using PlausibleIterStep.casesOn <;> simp [foldM_eq_forIn]
theorem IterM.fold_eq_forIn {α β γ : Type w} {m : Type w → Type w'} [Iterator α m β]
[Finite α m] [Monad m]
[IteratorLoop α m m] {f : γ → β → γ} {init : γ} {it : IterM (α := α) m β} :
it.fold (init := init) f =
ForIn.forIn (m := m) it init (fun x acc => pure (ForInStep.yield (f acc x))) := by
rfl
theorem IterM.fold_eq_foldM {α β γ : Type w} {m : Type w → Type w'} [Iterator α m β]
[Finite α m] [Monad m] [LawfulMonad m] [IteratorLoop α m m] {f : γ → β → γ} {init : γ}
{it : IterM (α := α) m β} :
it.fold (init := init) f = it.foldM (init := init) (pure <| f · ·) := by
simp [foldM_eq_forIn, fold_eq_forIn]
@[simp]
theorem IterM.forIn_pure_yield_eq_fold {α β γ : Type w} {m : Type w → Type w'} [Iterator α m β]
[Finite α m] [Monad m] [LawfulMonad m] [IteratorLoop α m m]
[LawfulIteratorLoop α m m] {f : β → γγ} {init : γ}
{it : IterM (α := α) m β} :
ForIn.forIn it init (fun c b => pure (.yield (f c b))) =
it.fold (fun b c => f c b) init := by
simp [IterM.fold_eq_forIn]
theorem IterM.fold_eq_match_step {α β γ : Type w} {m : Type w → Type w'} [Iterator α m β] [Finite α m]
[Monad m] [LawfulMonad m] [IteratorLoop α m m] [LawfulIteratorLoop α m m]
{f : γ → β → γ} {init : γ} {it : IterM (α := α) m β} :
it.fold (init := init) f = (do
match ← it.step with
| .yield it' out _ => it'.fold (init := f init out) f
| .skip it' _ => it'.fold (init := init) f
| .done _ => return init) := by
rw [fold_eq_foldM, foldM_eq_match_step]
simp only [fold_eq_foldM]
apply bind_congr
intro step
cases step using PlausibleIterStep.casesOn <;> simp
theorem IterM.toList_eq_fold {α β : Type w} {m : Type w → Type w'} [Iterator α m β]
[Finite α m] [Monad m] [LawfulMonad m] [IteratorLoop α m m] [LawfulIteratorLoop α m m]
[IteratorCollect α m m] [LawfulIteratorCollect α m m]
{it : IterM (α := α) m β} :
it.toList = it.fold (init := []) (fun l out => l ++ [out]) := by
suffices h : ∀ l' : List β, (l' ++ ·) <$> it.toList =
it.fold (init := l') (fun l out => l ++ [out]) by
specialize h []
simpa using h
induction it using IterM.inductSteps with | step it ihy ihs =>
intro l'
rw [IterM.toList_eq_match_step, IterM.fold_eq_match_step]
simp only [map_eq_pure_bind, bind_assoc]
apply bind_congr
intro step
cases step using PlausibleIterStep.casesOn
· rename_i it' out h
specialize ihy h (l' ++ [out])
simpa using ihy
· rename_i it' h
simp [ihs h]
· simp
theorem IterM.drain_eq_fold {α β : Type w} {m : Type w → Type w'} [Iterator α m β] [Finite α m]
[Monad m] [IteratorLoop α m m] {it : IterM (α := α) m β} :
it.drain = it.fold (init := PUnit.unit) (fun _ _ => .unit) :=
(rfl)
theorem IterM.drain_eq_foldM {α β : Type w} {m : Type w → Type w'} [Iterator α m β] [Finite α m]
[Monad m] [LawfulMonad m] [IteratorLoop α m m] {it : IterM (α := α) m β} :
it.drain = it.foldM (init := PUnit.unit) (fun _ _ => pure .unit) := by
simp [IterM.drain_eq_fold, IterM.fold_eq_foldM]
theorem IterM.drain_eq_forIn {α β : Type w} {m : Type w → Type w'} [Iterator α m β] [Finite α m]
[Monad m] [IteratorLoop α m m] {it : IterM (α := α) m β} :
it.drain = ForIn.forIn (m := m) it PUnit.unit (fun _ _ => pure (ForInStep.yield .unit)) := by
simp [IterM.drain_eq_fold, IterM.fold_eq_forIn]
theorem IterM.drain_eq_match_step {α β : Type w} {m : Type w → Type w'} [Iterator α m β] [Finite α m]
[Monad m] [LawfulMonad m] [IteratorLoop α m m] [LawfulIteratorLoop α m m]
{it : IterM (α := α) m β} :
it.drain = (do
match ← it.step with
| .yield it' _ _ => it'.drain
| .skip it' _ => it'.drain
| .done _ => return .unit) := by
rw [IterM.drain_eq_fold, IterM.fold_eq_match_step]
simp [IterM.drain_eq_fold]
theorem IterM.drain_eq_map_toList {α β : Type w} {m : Type w → Type w'} [Iterator α m β]
[Finite α m] [Monad m] [LawfulMonad m] [IteratorLoop α m m] [LawfulIteratorLoop α m m]
[IteratorCollect α m m] [LawfulIteratorCollect α m m]
{it : IterM (α := α) m β} :
it.drain = (fun _ => .unit) <$> it.toList := by
induction it using IterM.inductSteps with | step it ihy ihs =>
rw [IterM.drain_eq_match_step, IterM.toList_eq_match_step]
simp only [map_eq_pure_bind, bind_assoc]
apply bind_congr
intro step
cases step using PlausibleIterStep.casesOn
· rename_i it' out h
simp [ihy h]
· rename_i it' h
simp [ihs h]
· simp
theorem IterM.drain_eq_map_toListRev {α β : Type w} {m : Type w → Type w'} [Iterator α m β]
[Finite α m] [Monad m] [LawfulMonad m] [IteratorLoop α m m] [LawfulIteratorLoop α m m]
[IteratorCollect α m m] [LawfulIteratorCollect α m m]
{it : IterM (α := α) m β} :
it.drain = (fun _ => .unit) <$> it.toListRev := by
simp [IterM.drain_eq_map_toList, IterM.toListRev_eq]
theorem IterM.drain_eq_map_toArray {α β : Type w} {m : Type w → Type w'} [Iterator α m β]
[Finite α m] [Monad m] [LawfulMonad m] [IteratorLoop α m m] [LawfulIteratorLoop α m m]
[IteratorCollect α m m] [LawfulIteratorCollect α m m]
{it : IterM (α := α) m β} :
it.drain = (fun _ => .unit) <$> it.toList := by
simp [IterM.drain_eq_map_toList]
end Std.Iterators

View file

@ -3,8 +3,10 @@ Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Paul Reichert
-/
module
prelude
import Std.Data.Iterators.Basic
import Init.Data.Iterators.Basic
namespace Std.Iterators

View file

@ -3,6 +3,8 @@ Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Paul Reichert
-/
module
prelude
import Init.Control.Lawful.Basic
import Init.Data.Subtype
@ -48,6 +50,7 @@ def PostconditionT.lift {α : Type w} {m : Type w → Type w'} [Functor m] (x :
PostconditionT m α :=
⟨fun _ => True, (⟨·, .intro⟩) <$> x⟩
@[always_inline, inline]
protected def PostconditionT.pure {m : Type w → Type w'} [Pure m] {α : Type w}
(a : α) : PostconditionT m α :=
⟨fun y => a = y, pure <| ⟨a, rfl⟩⟩
@ -117,16 +120,20 @@ instance {m : Type w → Type w'} [Monad m] : Monad (PostconditionT m) where
pure := PostconditionT.pure
bind := PostconditionT.bind
@[simp]
theorem PostconditionT.computation_pure {m : Type w → Type w'} [Monad m] {α : Type w}
{x : α} :
(pure x : PostconditionT m α).operation = pure ⟨x, rfl⟩ :=
theorem PostconditionT.pure_eq_pure {m : Type w → Type w'} [Monad m] {α} {a : α} :
pure a = PostconditionT.pure (m := m) a :=
rfl
@[simp]
theorem PostconditionT.property_pure {m : Type w → Type w'} [Monad m] {α : Type w}
{x : α} :
(pure x : PostconditionT m α).Property = (x = ·) :=
(pure x : PostconditionT m α).Property = (x = ·) := by
rfl
@[simp]
theorem PostconditionT.operation_pure {m : Type w → Type w'} [Monad m] {α : Type w}
{x : α} :
(pure x : PostconditionT m α).operation = pure ⟨x, property_pure (m := m) ▸ rfl⟩ := by
rfl
theorem PostconditionT.ext {m : Type w → Type w'} [Monad m] [LawfulMonad m]
@ -209,12 +216,19 @@ theorem PostconditionT.property_map {m : Type w → Type w'} [Functor m] {α : T
@[simp]
theorem PostconditionT.operation_map {m : Type w → Type w'} [Functor m] {α : Type w} {β : Type w}
{x : PostconditionT m α} {f : α → β} :
(x.map f).operation = (fun a => ⟨_, a, rfl⟩) <$> x.operation :=
(x.map f).operation =
(fun a => ⟨_, (property_map (m := m)).mpr ⟨a.1, rfl, a.2⟩⟩) <$> x.operation := by
rfl
@[simp]
theorem PostconditionT.operation_lift {m : Type w →Type w'} [Functor m] {α : Type w}
{x : m α} : (lift x : PostconditionT m α).operation = (⟨·, True.intro⟩) <$> x :=
theorem PostconditionT.property_lift {m : Type w → Type w'} [Functor m] {α : Type w}
{x : m α} : (lift x : PostconditionT m α).Property = (fun _ => True) := by
rfl
@[simp]
theorem PostconditionT.operation_lift {m : Type w → Type w'} [Functor m] {α : Type w}
{x : m α} : (lift x : PostconditionT m α).operation =
(⟨·, property_lift (m := m) ▸ True.intro⟩) <$> x := by
rfl
end Std.Iterators

View file

@ -4,13 +4,13 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Paul Reichert
-/
prelude
import Std.Data.Iterators.Basic
import Init.Data.Iterators.Basic
import Init.Data.Iterators.Consumers
import Init.Data.Iterators.PostconditionMonad
import Init.Data.Iterators.Internal
import Std.Data.Iterators.Producers
import Std.Data.Iterators.Consumers
import Std.Data.Iterators.Combinators
import Std.Data.Iterators.Lemmas
import Std.Data.Iterators.PostConditionMonad
import Std.Data.Iterators.Internal
/-!
# Iterators
@ -79,7 +79,9 @@ that needs to wait for a language feature.
A distinction that cuts through the whole module is that between pure and monadic
iterators. Each submodule contains a dedicated `Monadic` sub-submodule.
All of the following module names are prefixed with `Std.Data.Iterators`.
Depending on whether functionality is needed in `Init`, modules might exist in `Init` or in `Std`.
The following module names can then be found under `Init.Data.Iterators`, `Std.Data.Iterators` or
both.
### Basic iterator API

View file

@ -4,10 +4,10 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Paul Reichert
-/
prelude
import Std.Data.Iterators.Basic
import Std.Data.Iterators.Consumers.Collect
import Std.Data.Iterators.Consumers.Loop
import Std.Data.Iterators.Internal.Termination
import Init.Data.Iterators.Basic
import Init.Data.Iterators.Consumers.Collect
import Init.Data.Iterators.Consumers.Loop
import Init.Data.Iterators.Internal.Termination
/-!
This file provides the iterator combinator `IterM.drop`.

View file

@ -6,11 +6,11 @@ Authors: Paul Reichert
prelude
import Init.Data.Nat.Lemmas
import Init.RCases
import Std.Data.Iterators.Basic
import Std.Data.Iterators.Consumers.Monadic.Collect
import Std.Data.Iterators.Consumers.Monadic.Loop
import Std.Data.Iterators.Internal.Termination
import Std.Data.Iterators.PostConditionMonad
import Init.Data.Iterators.Basic
import Init.Data.Iterators.Consumers.Monadic.Collect
import Init.Data.Iterators.Consumers.Monadic.Loop
import Init.Data.Iterators.Internal.Termination
import Init.Data.Iterators.PostconditionMonad
/-!
# Monadic `dropWhile` iterator combinator

View file

@ -4,11 +4,11 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Paul Reichert
-/
prelude
import Std.Data.Iterators.Basic
import Std.Data.Iterators.Consumers.Collect
import Std.Data.Iterators.Consumers.Loop
import Std.Data.Iterators.PostConditionMonad
import Std.Data.Iterators.Internal.Termination
import Init.Data.Iterators.Basic
import Init.Data.Iterators.Consumers.Collect
import Init.Data.Iterators.Consumers.Loop
import Init.Data.Iterators.PostconditionMonad
import Init.Data.Iterators.Internal.Termination
/-!

View file

@ -6,10 +6,10 @@ Authors: Paul Reichert
prelude
import Init.Data.Nat.Lemmas
import Init.RCases
import Std.Data.Iterators.Basic
import Std.Data.Iterators.Consumers.Monadic.Collect
import Std.Data.Iterators.Consumers.Monadic.Loop
import Std.Data.Iterators.Internal.Termination
import Init.Data.Iterators.Basic
import Init.Data.Iterators.Consumers.Monadic.Collect
import Init.Data.Iterators.Consumers.Monadic.Loop
import Init.Data.Iterators.Internal.Termination
/-!
This module provides the iterator combinator `IterM.take`.
@ -143,15 +143,9 @@ instance Take.instIteratorLoop [Monad m] [Monad n] [Iterator α m β]
IteratorLoop (Take α m β) m n :=
.defaultImplementation
instance Take.instIteratorForPartial [Monad m] [Monad n] [Iterator α m β]
instance Take.instIteratorLoopPartial [Monad m] [Monad n] [Iterator α m β]
[IteratorLoopPartial α m n] [MonadLiftT m n] :
IteratorLoopPartial (Take α m β) m n where
forInPartial lift {γ} it init f := do
Prod.fst <$> IteratorLoopPartial.forInPartial lift it.internalState.inner (γ := γ × Nat)
(init, it.internalState.remaining)
fun out acc =>
match acc.snd with
| 0 => pure <| .done acc
| n + 1 => (fun | .yield x => .yield ⟨x, n⟩ | .done x => .done ⟨x, n⟩) <$> f out acc.fst
IteratorLoopPartial (Take α m β) m n :=
.defaultImplementation
end Std.Iterators

View file

@ -6,11 +6,11 @@ Authors: Paul Reichert
prelude
import Init.Data.Nat.Lemmas
import Init.RCases
import Std.Data.Iterators.Basic
import Std.Data.Iterators.Consumers.Monadic.Collect
import Std.Data.Iterators.Consumers.Monadic.Loop
import Std.Data.Iterators.Internal.Termination
import Std.Data.Iterators.PostConditionMonad
import Init.Data.Iterators.Basic
import Init.Data.Iterators.Consumers.Monadic.Collect
import Init.Data.Iterators.Consumers.Monadic.Loop
import Init.Data.Iterators.Internal.Termination
import Init.Data.Iterators.PostconditionMonad
/-!
# Monadic `takeWhile` iterator combinator

View file

@ -5,10 +5,10 @@ Authors: Paul Reichert
-/
prelude
import Init.Data.Option.Lemmas
import Std.Data.Iterators.Basic
import Std.Data.Iterators.Consumers.Collect
import Std.Data.Iterators.Consumers.Loop
import Std.Data.Iterators.Internal.Termination
import Init.Data.Iterators.Basic
import Init.Data.Iterators.Consumers.Collect
import Init.Data.Iterators.Consumers.Loop
import Init.Data.Iterators.Internal.Termination
/-!

View file

@ -1,11 +0,0 @@
/-
Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Paul Reichert
-/
prelude
import Std.Data.Iterators.Consumers.Monadic
import Std.Data.Iterators.Consumers.Access
import Std.Data.Iterators.Consumers.Collect
import Std.Data.Iterators.Consumers.Loop
import Std.Data.Iterators.Consumers.Partial

View file

@ -4,9 +4,8 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Paul Reichert
-/
prelude
import Std.Data.Iterators.Lemmas.Basic
import Init.Data.Iterators.Lemmas.Basic
import Std.Data.Iterators.Lemmas.Monadic
import Std.Data.Iterators.Lemmas.Consumers
import Std.Data.Iterators.Lemmas.Combinators
import Std.Data.Iterators.Lemmas.Producers
import Std.Data.Iterators.Lemmas.Equivalence

View file

@ -7,7 +7,7 @@ prelude
import Std.Data.Iterators.Combinators.Drop
import Std.Data.Iterators.Lemmas.Combinators.Monadic.Drop
import Std.Data.Iterators.Lemmas.Combinators.Take
import Std.Data.Iterators.Lemmas.Consumers
import Init.Data.Iterators.Lemmas.Consumers
namespace Std.Iterators

View file

@ -6,7 +6,7 @@ Authors: Paul Reichert
prelude
import Std.Data.Iterators.Combinators.DropWhile
import Std.Data.Iterators.Lemmas.Combinators.Monadic.DropWhile
import Std.Data.Iterators.Lemmas.Consumers
import Init.Data.Iterators.Lemmas.Consumers
namespace Std.Iterators

View file

@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Paul Reichert
-/
prelude
import Std.Data.Iterators.Lemmas.Consumers
import Init.Data.Iterators.Lemmas.Consumers
import Std.Data.Iterators.Lemmas.Combinators.Monadic.FilterMap
import Std.Data.Iterators.Combinators.FilterMap

View file

@ -5,7 +5,7 @@ Authors: Paul Reichert
-/
prelude
import Std.Data.Iterators.Combinators.Monadic.Drop
import Std.Data.Iterators.Lemmas.Consumers.Monadic
import Init.Data.Iterators.Lemmas.Consumers.Monadic
namespace Std.Iterators

View file

@ -5,7 +5,7 @@ Authors: Paul Reichert
-/
prelude
import Std.Data.Iterators.Combinators.Monadic.DropWhile
import Std.Data.Iterators.Lemmas.Consumers.Monadic
import Init.Data.Iterators.Lemmas.Consumers.Monadic
namespace Std.Iterators

View file

@ -4,9 +4,9 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Paul Reichert
-/
prelude
import Std.Data.Internal.LawfulMonadLiftFunction
import Init.Data.Iterators.Internal.LawfulMonadLiftFunction
import Std.Data.Iterators.Combinators.Monadic.FilterMap
import Std.Data.Iterators.Lemmas.Consumers.Monadic
import Init.Data.Iterators.Lemmas.Consumers.Monadic
import Std.Data.Iterators.Lemmas.Equivalence.StepCongr
namespace Std.Iterators

View file

@ -5,7 +5,7 @@ Authors: Paul Reichert
-/
prelude
import Std.Data.Iterators.Combinators.Monadic.Take
import Std.Data.Iterators.Lemmas.Consumers.Monadic
import Init.Data.Iterators.Lemmas.Consumers.Monadic
namespace Std.Iterators

View file

@ -5,7 +5,7 @@ Authors: Paul Reichert
-/
prelude
import Std.Data.Iterators.Combinators.Monadic.Zip
import Std.Data.Iterators.Lemmas.Consumers.Monadic
import Init.Data.Iterators.Lemmas.Consumers.Monadic
namespace Std.Iterators

View file

@ -5,9 +5,9 @@ Authors: Paul Reichert
-/
prelude
import Std.Data.Iterators.Combinators.Take
import Std.Data.Iterators.Consumers.Access
import Init.Data.Iterators.Consumers.Access
import Std.Data.Iterators.Lemmas.Combinators.Monadic.Take
import Std.Data.Iterators.Lemmas.Consumers
import Init.Data.Iterators.Lemmas.Consumers
namespace Std.Iterators

View file

@ -6,10 +6,10 @@ Authors: Paul Reichert
prelude
import Std.Data.Iterators.Combinators.Take
import Std.Data.Iterators.Combinators.Zip
import Std.Data.Iterators.Consumers.Access
import Init.Data.Iterators.Consumers.Access
import Std.Data.Iterators.Lemmas.Combinators.Monadic.Zip
import Std.Data.Iterators.Lemmas.Combinators.Take
import Std.Data.Iterators.Lemmas.Consumers
import Init.Data.Iterators.Lemmas.Consumers
namespace Std.Iterators

View file

@ -4,113 +4,14 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Paul Reichert
-/
prelude
import Std.Data.Iterators.Consumers.Access
import Std.Data.Iterators.Consumers.Collect
import Std.Data.Iterators.Lemmas.Basic
import Init.Data.Iterators.Consumers.Access
import Init.Data.Iterators.Consumers.Collect
import Init.Data.Iterators.Lemmas.Consumers.Collect
import Init.Data.Iterators.Lemmas.Basic
import Std.Data.Iterators.Lemmas.Consumers.Monadic.Collect
namespace Std.Iterators
theorem Iter.toArray_eq_toArray_toIterM {α β} [Iterator α Id β] [Finite α Id] [IteratorCollect α Id Id]
[LawfulIteratorCollect α Id Id] {it : Iter (α := α) β} :
it.toArray = it.toIterM.toArray.run :=
rfl
theorem Iter.toList_eq_toList_toIterM {α β} [Iterator α Id β] [Finite α Id] [IteratorCollect α Id Id]
[LawfulIteratorCollect α Id Id] {it : Iter (α := α) β} :
it.toList = it.toIterM.toList.run :=
rfl
theorem Iter.toListRev_eq_toListRev_toIterM {α β} [Iterator α Id β] [Finite α Id]
{it : Iter (α := α) β} :
it.toListRev = it.toIterM.toListRev.run :=
rfl
@[simp]
theorem IterM.toList_toIter {α β} [Iterator α Id β] [Finite α Id] [IteratorCollect α Id Id]
{it : IterM (α := α) Id β} :
it.toIter.toList = it.toList.run :=
rfl
@[simp]
theorem IterM.toListRev_toIter {α β} [Iterator α Id β] [Finite α Id]
{it : IterM (α := α) Id β} :
it.toIter.toListRev = it.toListRev.run :=
rfl
theorem Iter.toList_toArray {α β} [Iterator α Id β] [Finite α Id] [IteratorCollect α Id Id]
[LawfulIteratorCollect α Id Id] {it : Iter (α := α) β} :
it.toArray.toList = it.toList := by
simp [toArray_eq_toArray_toIterM, toList_eq_toList_toIterM, ← IterM.toList_toArray]
theorem Iter.toArray_toList {α β} [Iterator α Id β] [Finite α Id] [IteratorCollect α Id Id]
[LawfulIteratorCollect α Id Id] {it : Iter (α := α) β} :
it.toList.toArray = it.toArray := by
simp [toArray_eq_toArray_toIterM, toList_eq_toList_toIterM, ← IterM.toArray_toList]
@[simp]
theorem Iter.reverse_toListRev [Iterator α Id β] [Finite α Id]
[IteratorCollect α Id Id] [LawfulIteratorCollect α Id Id]
{it : Iter (α := α) β} :
it.toListRev.reverse = it.toList := by
simp [toListRev_eq_toListRev_toIterM, toList_eq_toList_toIterM, ← IterM.reverse_toListRev]
theorem Iter.toListRev_eq {α β} [Iterator α Id β] [Finite α Id] [IteratorCollect α Id Id]
[LawfulIteratorCollect α Id Id] {it : Iter (α := α) β} :
it.toListRev = it.toList.reverse := by
simp [Iter.toListRev_eq_toListRev_toIterM, Iter.toList_eq_toList_toIterM, IterM.toListRev_eq]
theorem Iter.toArray_eq_match_step {α β} [Iterator α Id β] [Finite α Id] [IteratorCollect α Id Id]
[LawfulIteratorCollect α Id Id] {it : Iter (α := α) β} :
it.toArray = match it.step with
| .yield it' out _ => #[out] ++ it'.toArray
| .skip it' _ => it'.toArray
| .done _ => #[] := by
simp only [Iter.toArray_eq_toArray_toIterM, Iter.step]
rw [IterM.toArray_eq_match_step, Id.run_bind]
generalize it.toIterM.step.run = step
cases step using PlausibleIterStep.casesOn <;> simp
theorem Iter.toList_eq_match_step {α β} [Iterator α Id β] [Finite α Id] [IteratorCollect α Id Id]
[LawfulIteratorCollect α Id Id] {it : Iter (α := α) β} :
it.toList = match it.step with
| .yield it' out _ => out :: it'.toList
| .skip it' _ => it'.toList
| .done _ => [] := by
rw [← Iter.toList_toArray, Iter.toArray_eq_match_step]
split <;> simp [Iter.toList_toArray]
theorem Iter.toListRev_eq_match_step {α β} [Iterator α Id β] [Finite α Id] {it : Iter (α := α) β} :
it.toListRev = match it.step with
| .yield it' out _ => it'.toListRev ++ [out]
| .skip it' _ => it'.toListRev
| .done _ => [] := by
rw [Iter.toListRev_eq_toListRev_toIterM, IterM.toListRev_eq_match_step, Iter.step, Id.run_bind]
generalize it.toIterM.step.run = step
cases step using PlausibleIterStep.casesOn <;> simp
theorem Iter.getElem?_toList_eq_atIdxSlow? {α β}
[Iterator α Id β] [Finite α Id] [IteratorCollect α Id Id] [LawfulIteratorCollect α Id Id]
{it : Iter (α := α) β} {k : Nat} :
it.toList[k]? = it.atIdxSlow? k := by
induction it using Iter.inductSteps generalizing k with | step it ihy ihs =>
rw [toList_eq_match_step, atIdxSlow?]
obtain ⟨step, h⟩ := it.step
cases step
· cases k <;> simp [ihy h]
· simp [ihs h]
· simp
theorem Iter.toList_eq_of_atIdxSlow?_eq {α₁ α₂ β}
[Iterator α₁ Id β] [Finite α₁ Id] [IteratorCollect α₁ Id Id] [LawfulIteratorCollect α₁ Id Id]
[Iterator α₂ Id β] [Finite α₂ Id] [IteratorCollect α₂ Id Id] [LawfulIteratorCollect α₂ Id Id]
{it₁ : Iter (α := α₁) β} {it₂ : Iter (α := α₂) β}
(h : ∀ k, it₁.atIdxSlow? k = it₂.atIdxSlow? k) :
it₁.toList = it₂.toList := by
ext; simp [getElem?_toList_eq_atIdxSlow?, h]
section Equivalence
theorem Iter.Equiv.toListRev_eq
[Iterator α₁ Id β] [Iterator α₂ Id β] [Finite α₁ Id] [Finite α₂ Id]
{ita : Iter (α := α₁) β} {itb : Iter (α := α₂) β} (h : Iter.Equiv ita itb) :
@ -133,6 +34,4 @@ theorem Iter.Equiv.toArray_eq
ita.toArray = itb.toArray := by
simp only [← Iter.toArray_toList, toList_eq h]
end Equivalence
end Std.Iterators

View file

@ -5,179 +5,15 @@ Authors: Paul Reichert
-/
prelude
import Init.Data.List.Control
import Std.Data.Iterators.Lemmas.Basic
import Init.Data.Iterators.Lemmas.Basic
import Init.Data.Iterators.Lemmas.Consumers.Loop
import Std.Data.Iterators.Lemmas.Consumers.Collect
import Std.Data.Iterators.Lemmas.Consumers.Monadic.Loop
import Std.Data.Iterators.Consumers.Collect
import Std.Data.Iterators.Consumers.Loop
import Init.Data.Iterators.Consumers.Collect
import Init.Data.Iterators.Consumers.Loop
namespace Std.Iterators
theorem Iter.forIn_eq {α β : Type w} [Iterator α Id β] [Finite α Id]
{m : Type w → Type w''} [Monad m] [IteratorLoop α Id m] [hl : LawfulIteratorLoop α Id m]
{γ : Type w} {it : Iter (α := α) β} {init : γ}
{f : β → γ → m (ForInStep γ)} :
ForIn.forIn it init f =
IterM.DefaultConsumers.forIn (fun _ c => pure c.run) γ (fun _ _ _ => True)
IteratorLoop.wellFounded_of_finite it.toIterM init ((⟨·, .intro⟩) <$> f · ·) := by
cases hl.lawful; rfl
theorem Iter.forIn_eq_forIn_toIterM {α β : Type w} [Iterator α Id β]
[Finite α Id] {m : Type w → Type w''} [Monad m] [LawfulMonad m]
[IteratorLoop α Id m] [LawfulIteratorLoop α Id m]
{γ : Type w} {it : Iter (α := α) β} {init : γ}
{f : β → γ → m (ForInStep γ)} :
ForIn.forIn it init f =
letI : MonadLift Id m := ⟨Std.Internal.idToMonad (α := _)⟩
ForIn.forIn it.toIterM init f := by
rfl
theorem Iter.forIn_eq_match_step {α β : Type w} [Iterator α Id β]
[Finite α Id] {m : Type w → Type w''} [Monad m] [LawfulMonad m]
[IteratorLoop α Id m] [LawfulIteratorLoop α Id m]
{γ : Type w} {it : Iter (α := α) β} {init : γ}
{f : β → γ → m (ForInStep γ)} :
ForIn.forIn it init f = (do
match it.step with
| .yield it' out _ =>
match ← f out init with
| .yield c => ForIn.forIn it' c f
| .done c => return c
| .skip it' _ => ForIn.forIn it' init f
| .done _ => return init) := by
rw [Iter.forIn_eq_forIn_toIterM, @IterM.forIn_eq_match_step, Iter.step]
simp only [liftM, monadLift, pure_bind]
generalize it.toIterM.step = step
cases step using PlausibleIterStep.casesOn
· apply bind_congr
intro forInStep
rfl
· rfl
· rfl
theorem Iter.forIn_toList {α β : Type w} [Iterator α Id β]
[Finite α Id] {m : Type w → Type w''} [Monad m] [LawfulMonad m]
[IteratorLoop α Id m] [LawfulIteratorLoop α Id m]
[IteratorCollect α Id Id] [LawfulIteratorCollect α Id Id]
{γ : Type w} {it : Iter (α := α) β} {init : γ}
{f : β → γ → m (ForInStep γ)} :
ForIn.forIn it.toList init f = ForIn.forIn it init f := by
rw [List.forIn_eq_foldlM]
induction it using Iter.inductSteps generalizing init with case step it ihy ihs =>
rw [forIn_eq_match_step, Iter.toList_eq_match_step]
simp only [map_eq_pure_bind]
generalize it.step = step
cases step using PlausibleIterStep.casesOn
· rename_i it' out h
simp only [List.foldlM_cons, bind_pure_comp, map_bind]
apply bind_congr
intro forInStep
cases forInStep
· induction it'.toList <;> simp [*]
· simp only [ForIn.forIn, forIn', List.forIn'] at ihy
simp [ihy h, forIn_eq_forIn_toIterM]
· rename_i it' h
simp only [bind_pure_comp]
rw [ihs h]
· simp
theorem Iter.foldM_eq_forIn {α β γ : Type w} [Iterator α Id β] [Finite α Id] {m : Type w → Type w'}
[Monad m] [IteratorLoop α Id m] {f : γ → β → m γ}
{init : γ} {it : Iter (α := α) β} :
it.foldM (init := init) f = ForIn.forIn it init (fun x acc => ForInStep.yield <$> f acc x) :=
rfl
theorem Iter.foldM_eq_foldM_toIterM {α β : Type w} [Iterator α Id β]
[Finite α Id] {m : Type w → Type w''} [Monad m] [LawfulMonad m]
[IteratorLoop α Id m] [LawfulIteratorLoop α Id m]
{γ : Type w} {it : Iter (α := α) β} {init : γ} {f : γ → β → m γ} :
it.foldM (init := init) f = letI : MonadLift Id m := ⟨pure⟩; it.toIterM.foldM (init := init) f :=
rfl
theorem Iter.forIn_yield_eq_foldM {α β γ δ : Type w} [Iterator α Id β]
[Finite α Id] {m : Type w → Type w''} [Monad m] [LawfulMonad m] [IteratorLoop α Id m]
[LawfulIteratorLoop α Id m] {f : β → γ → m δ} {g : β → γ → δ → γ} {init : γ}
{it : Iter (α := α) β} :
ForIn.forIn it init (fun c b => (fun d => .yield (g c b d)) <$> f c b) =
it.foldM (fun b c => g c b <$> f c b) init := by
simp [Iter.foldM_eq_forIn]
theorem Iter.foldM_eq_match_step {α β γ : Type w} [Iterator α Id β] [Finite α Id]
{m : Type w → Type w'} [Monad m] [LawfulMonad m] [IteratorLoop α Id m]
[LawfulIteratorLoop α Id m] {f : γ → β → m γ} {init : γ} {it : Iter (α := α) β} :
it.foldM (init := init) f = (do
match it.step with
| .yield it' out _ => it'.foldM (init := ← f init out) f
| .skip it' _ => it'.foldM (init := init) f
| .done _ => return init) := by
rw [Iter.foldM_eq_forIn, Iter.forIn_eq_match_step]
generalize it.step = step
cases step using PlausibleIterStep.casesOn <;> simp [foldM_eq_forIn]
theorem Iter.foldlM_toList {α β γ : Type w} [Iterator α Id β] [Finite α Id] {m : Type w → Type w'}
[Monad m] [LawfulMonad m] [IteratorLoop α Id m] [LawfulIteratorLoop α Id m]
[IteratorCollect α Id Id] [LawfulIteratorCollect α Id Id]
{f : γ → β → m γ}
{init : γ} {it : Iter (α := α) β} :
it.toList.foldlM (init := init) f = it.foldM (init := init) f := by
rw [Iter.foldM_eq_forIn, ← Iter.forIn_toList]
simp only [List.forIn_yield_eq_foldlM, id_map']
theorem IterM.forIn_eq_foldM {α β : Type w} [Iterator α Id β]
[Finite α Id] {m : Type w → Type w''} [Monad m] [LawfulMonad m]
[IteratorLoop α Id m] [LawfulIteratorLoop α Id m]
[IteratorCollect α Id Id] [LawfulIteratorCollect α Id Id]
{γ : Type w} {it : Iter (α := α) β} {init : γ}
{f : β → γ → m (ForInStep γ)} :
forIn it init f = ForInStep.value <$>
it.foldM (fun c b => match c with
| .yield c => f b c
| .done c => pure (.done c)) (ForInStep.yield init) := by
simp only [← Iter.forIn_toList, List.forIn_eq_foldlM, ← Iter.foldlM_toList]; rfl
theorem Iter.fold_eq_forIn {α β γ : Type w} [Iterator α Id β]
[Finite α Id] [IteratorLoop α Id Id] {f : γ → β → γ} {init : γ} {it : Iter (α := α) β} :
it.fold (init := init) f =
(ForIn.forIn (m := Id) it init (fun x acc => pure (ForInStep.yield (f acc x)))).run := by
rfl
theorem Iter.fold_eq_foldM {α β γ : Type w} [Iterator α Id β]
[Finite α Id] [IteratorLoop α Id Id] {f : γ → β → γ} {init : γ}
{it : Iter (α := α) β} :
it.fold (init := init) f = (it.foldM (m := Id) (init := init) (pure <| f · ·)).run := by
simp [foldM_eq_forIn, fold_eq_forIn]
@[simp]
theorem Iter.forIn_pure_yield_eq_fold {α β γ : Type w} [Iterator α Id β]
[Finite α Id] [IteratorLoop α Id Id]
[LawfulIteratorLoop α Id Id] {f : β → γγ} {init : γ}
{it : Iter (α := α) β} :
ForIn.forIn (m := Id) it init (fun c b => pure (.yield (f c b))) =
pure (it.fold (fun b c => f c b) init) := by
simp only [fold_eq_forIn]
rfl
theorem Iter.fold_eq_match_step {α β γ : Type w} [Iterator α Id β] [Finite α Id]
[IteratorLoop α Id Id] [LawfulIteratorLoop α Id Id]
{f : γ → β → γ} {init : γ} {it : Iter (α := α) β} :
it.fold (init := init) f = (match it.step with
| .yield it' out _ => it'.fold (init := f init out) f
| .skip it' _ => it'.fold (init := init) f
| .done _ => init) := by
rw [fold_eq_foldM, foldM_eq_match_step]
simp only [fold_eq_foldM]
generalize it.step = step
cases step using PlausibleIterStep.casesOn <;> simp
theorem Iter.foldl_toList {α β γ : Type w} [Iterator α Id β] [Finite α Id]
[IteratorLoop α Id Id] [LawfulIteratorLoop α Id Id]
[IteratorCollect α Id Id] [LawfulIteratorCollect α Id Id]
{f : γ → β → γ} {init : γ} {it : Iter (α := α) β} :
it.toList.foldl (init := init) f = it.fold (init := init) f := by
rw [fold_eq_foldM, List.foldl_eq_foldlM, ← Iter.foldlM_toList]
section Equivalence
theorem Iter.Equiv.forIn_eq {α₁ α₂ β γ : Type w} {m : Type w → Type w'}
[Iterator α₁ Id β] [Iterator α₂ Id β] [Finite α₁ Id] [Finite α₂ Id]
[Monad m] [LawfulMonad m] [IteratorLoop α₁ Id m] [LawfulIteratorLoop α₁ Id m]
@ -208,6 +44,4 @@ theorem Iter.Equiv.fold_eq {α₁ α₂ β γ : Type w} {m : Type w → Type w'}
ita.fold (init := init) f = itb.fold (init := init) f := by
simp [Iter.fold_eq_foldM, h.foldM_eq]
end Equivalence
end Std.Iterators

View file

@ -5,161 +5,13 @@ Authors: Paul Reichert
-/
prelude
import Init.Data.Array.Lemmas
import Std.Data.Iterators.Consumers.Monadic.Collect
import Std.Data.Iterators.Lemmas.Monadic.Basic
import Std.Data.Iterators.Producers
import Init.Data.Iterators.Consumers.Monadic.Collect
import Init.Data.Iterators.Lemmas.Consumers.Monadic.Collect
import Init.Data.Iterators.Lemmas.Monadic.Basic
import Std.Data.Iterators.Lemmas.Equivalence.StepCongr
namespace Std.Iterators
section Consumers
variable {α β γ : Type w} {m : Type w → Type w'} {n : Type w → Type w''}
{lift : ⦃δ : Type w⦄ → m δ → n δ} {f : β → n γ} {it : IterM (α := α) m β}
theorem IterM.DefaultConsumers.toArrayMapped.go.aux₁ [Monad n] [LawfulMonad n] [Iterator α m β]
[Finite α m] {b : γ} {bs : Array γ} :
IterM.DefaultConsumers.toArrayMapped.go lift f it (#[b] ++ bs) (m := m) =
(#[b] ++ ·) <$> IterM.DefaultConsumers.toArrayMapped.go lift f it bs (m := m) := by
induction it, bs using IterM.DefaultConsumers.toArrayMapped.go.induct
next it bs ih₁ ih₂ =>
rw [go, map_eq_pure_bind, go, bind_assoc]
apply bind_congr
intro step
split
· simp [ih₁ _ _ _]
· simp [ih₂ _ _]
· simp
theorem IterM.DefaultConsumers.toArrayMapped.go.aux₂ [Monad n] [LawfulMonad n] [Iterator α m β]
[Finite α m] {acc : Array γ} :
IterM.DefaultConsumers.toArrayMapped.go lift f it acc (m := m) =
(acc ++ ·) <$> IterM.DefaultConsumers.toArrayMapped lift f it (m := m) := by
rw [← Array.toArray_toList (xs := acc)]
generalize acc.toList = acc
induction acc with
| nil => simp [toArrayMapped]
| cons x xs ih =>
rw [List.toArray_cons, IterM.DefaultConsumers.toArrayMapped.go.aux₁, ih]
simp only [Functor.map_map, Array.append_assoc]
theorem IterM.DefaultConsumers.toArrayMapped_eq_match_step [Monad n] [LawfulMonad n]
[Iterator α m β] [Finite α m] :
IterM.DefaultConsumers.toArrayMapped lift f it (m := m) = letI : MonadLift m n := ⟨lift (δ := _)⟩; (do
match ← it.step with
| .yield it' out _ =>
return #[← f out] ++ (← IterM.DefaultConsumers.toArrayMapped lift f it' (m := m))
| .skip it' _ => IterM.DefaultConsumers.toArrayMapped lift f it' (m := m)
| .done _ => return #[]) := by
rw [IterM.DefaultConsumers.toArrayMapped, IterM.DefaultConsumers.toArrayMapped.go]
apply bind_congr
intro step
split <;> simp [IterM.DefaultConsumers.toArrayMapped.go.aux₂]
theorem IterM.toArray_eq_match_step [Monad m] [LawfulMonad m] [Iterator α m β] [Finite α m]
[IteratorCollect α m m] [LawfulIteratorCollect α m m] :
it.toArray = (do
match ← it.step with
| .yield it' out _ => return #[out] ++ (← it'.toArray)
| .skip it' _ => it'.toArray
| .done _ => return #[]) := by
simp only [IterM.toArray, LawfulIteratorCollect.toArrayMapped_eq]
rw [IterM.DefaultConsumers.toArrayMapped_eq_match_step]
simp [bind_pure_comp, pure_bind, toArray]
theorem IterM.toList_toArray [Monad m] [Iterator α m β] [Finite α m] [IteratorCollect α m m]
{it : IterM (α := α) m β} :
Array.toList <$> it.toArray = it.toList := by
simp [IterM.toList]
theorem IterM.toArray_toList [Monad m] [LawfulMonad m] [Iterator α m β] [Finite α m]
[IteratorCollect α m m] {it : IterM (α := α) m β} :
List.toArray <$> it.toList = it.toArray := by
simp [IterM.toList]
theorem IterM.toList_eq_match_step [Monad m] [LawfulMonad m] [Iterator α m β] [Finite α m]
[IteratorCollect α m m] [LawfulIteratorCollect α m m] {it : IterM (α := α) m β} :
it.toList = (do
match ← it.step with
| .yield it' out _ => return out :: (← it'.toList)
| .skip it' _ => it'.toList
| .done _ => return []) := by
simp [← IterM.toList_toArray]
rw [IterM.toArray_eq_match_step, map_eq_pure_bind, bind_assoc]
apply bind_congr
intro step
split <;> simp
theorem IterM.toListRev.go.aux₁ [Monad m] [LawfulMonad m] [Iterator α m β] [Finite α m]
{it : IterM (α := α) m β} {b : β} {bs : List β} :
IterM.toListRev.go it (bs ++ [b]) = (· ++ [b]) <$> IterM.toListRev.go it bs:= by
induction it, bs using IterM.toListRev.go.induct
next it bs ih₁ ih₂ =>
rw [go, go, map_eq_pure_bind, bind_assoc]
apply bind_congr
intro step
simp only [List.cons_append] at ih₁
split <;> simp [*]
theorem IterM.toListRev.go.aux₂ [Monad m] [LawfulMonad m] [Iterator α m β] [Finite α m]
{it : IterM (α := α) m β} {acc : List β} :
IterM.toListRev.go it acc = (· ++ acc) <$> it.toListRev := by
rw [← List.reverse_reverse (as := acc)]
generalize acc.reverse = acc
induction acc with
| nil => simp [toListRev]
| cons x xs ih => simp [IterM.toListRev.go.aux₁, ih]
theorem IterM.toListRev_eq_match_step [Monad m] [LawfulMonad m] [Iterator α m β] [Finite α m]
{it : IterM (α := α) m β} :
it.toListRev = (do
match ← it.step with
| .yield it' out _ => return (← it'.toListRev) ++ [out]
| .skip it' _ => it'.toListRev
| .done _ => return []) := by
simp [IterM.toListRev]
rw [toListRev.go]
apply bind_congr
intro step
cases step using PlausibleIterStep.casesOn <;> simp [IterM.toListRev.go.aux₂]
theorem IterM.reverse_toListRev [Monad m] [LawfulMonad m] [Iterator α m β] [Finite α m]
[IteratorCollect α m m] [LawfulIteratorCollect α m m]
{it : IterM (α := α) m β} :
List.reverse <$> it.toListRev = it.toList := by
apply Eq.symm
induction it using IterM.inductSteps
rename_i it ihy ihs
rw [toListRev_eq_match_step, toList_eq_match_step, map_eq_pure_bind, bind_assoc]
apply bind_congr
intro step
split <;> simp (discharger := assumption) [ihy, ihs]
theorem IterM.toListRev_eq [Monad m] [LawfulMonad m] [Iterator α m β] [Finite α m]
[IteratorCollect α m m] [LawfulIteratorCollect α m m]
{it : IterM (α := α) m β} :
it.toListRev = List.reverse <$> it.toList := by
rw [← IterM.reverse_toListRev]
simp
theorem LawfulIteratorCollect.toArray_eq {α β : Type w} {m : Type w → Type w'}
[Monad m] [Iterator α m β] [Finite α m] [IteratorCollect α m m]
[hl : LawfulIteratorCollect α m m]
{it : IterM (α := α) m β} :
it.toArray = (letI : IteratorCollect α m m := .defaultImplementation; it.toArray) := by
simp only [IterM.toArray, toArrayMapped_eq]
theorem LawfulIteratorCollect.toList_eq {α β : Type w} {m : Type w → Type w'}
[Monad m] [Iterator α m β] [Finite α m] [IteratorCollect α m m]
[hl : LawfulIteratorCollect α m m]
{it : IterM (α := α) m β} :
it.toList = (letI : IteratorCollect α m m := .defaultImplementation; it.toList) := by
simp [IterM.toList, toArray_eq]
end Consumers
section Equivalence
theorem IterM.Equiv.toListRev_eq [Monad m] [LawfulMonad m]
[Iterator α₁ m β] [Iterator α₂ m β] [Finite α₁ m] [Finite α₂ m]
{ita : IterM (α := α₁) m β} {itb : IterM (α := α₂) m β} (h : IterM.Equiv ita itb) :
@ -197,6 +49,4 @@ theorem IterM.Equiv.toArray_eq [Monad m] [LawfulMonad m]
ita.toArray = itb.toArray := by
simp only [← IterM.toArray_toList, toList_eq h]
end Equivalence
end Std.Iterators

View file

@ -5,237 +5,15 @@ Authors: Paul Reichert
-/
prelude
import Init.Control.Lawful.Basic
import Std.Data.Iterators.Consumers.Monadic.Collect
import Std.Data.Iterators.Consumers.Monadic.Loop
import Std.Data.Iterators.Lemmas.Monadic.Basic
import Init.Data.Iterators.Consumers.Monadic.Collect
import Init.Data.Iterators.Consumers.Monadic.Loop
import Init.Data.Iterators.Lemmas.Monadic.Basic
import Init.Data.Iterators.Lemmas.Consumers.Monadic.Loop
import Std.Data.Iterators.Lemmas.Consumers.Monadic.Collect
import Std.Data.Iterators.Lemmas.Equivalence.StepCongr
namespace Std.Iterators
theorem IterM.DefaultConsumers.forIn_eq_match_step {α β : Type w} {m : Type w → Type w'}
[Iterator α m β]
{n : Type w → Type w''} [Monad n]
{lift : ∀ γ, m γ → n γ} {γ : Type w}
{plausible_forInStep : β → γ → ForInStep γ → Prop}
{wf : IteratorLoop.WellFounded α m plausible_forInStep}
{it : IterM (α := α) m β} {init : γ}
{f : (b : β) → (c : γ) → n (Subtype (plausible_forInStep b c))} :
IterM.DefaultConsumers.forIn lift γ plausible_forInStep wf it init f = (do
match ← lift _ it.step with
| .yield it' out _ =>
match ← f out init with
| ⟨.yield c, _⟩ => IterM.DefaultConsumers.forIn lift _ plausible_forInStep wf it' c f
| ⟨.done c, _⟩ => return c
| .skip it' _ => IterM.DefaultConsumers.forIn lift _ plausible_forInStep wf it' init f
| .done _ => return init) := by
rw [forIn]
apply bind_congr
intro step
cases step using PlausibleIterStep.casesOn <;> rfl
theorem IterM.forIn_eq {α β : Type w} {m : Type w → Type w'} [Iterator α m β] [Finite α m]
{n : Type w → Type w''} [Monad n] [IteratorLoop α m n] [hl : LawfulIteratorLoop α m n]
[MonadLiftT m n] {γ : Type w} {it : IterM (α := α) m β} {init : γ}
{f : β → γ → n (ForInStep γ)} :
ForIn.forIn it init f = IterM.DefaultConsumers.forIn (fun _ => monadLift) γ (fun _ _ _ => True)
IteratorLoop.wellFounded_of_finite it init ((⟨·, .intro⟩) <$> f · ·) := by
cases hl.lawful; rfl
theorem IterM.forIn_eq_match_step {α β : Type w} {m : Type w → Type w'} [Iterator α m β]
[Finite α m] {n : Type w → Type w''} [Monad n] [LawfulMonad n]
[IteratorLoop α m n] [LawfulIteratorLoop α m n]
[MonadLiftT m n] {γ : Type w} {it : IterM (α := α) m β} {init : γ}
{f : β → γ → n (ForInStep γ)} :
ForIn.forIn it init f = (do
match ← it.step with
| .yield it' out _ =>
match ← f out init with
| .yield c => ForIn.forIn it' c f
| .done c => return c
| .skip it' _ => ForIn.forIn it' init f
| .done _ => return init) := by
rw [IterM.forIn_eq, DefaultConsumers.forIn_eq_match_step]
apply bind_congr
intro step
cases step using PlausibleIterStep.casesOn
· simp only [map_eq_pure_bind, bind_assoc]
apply bind_congr
intro forInStep
cases forInStep <;> simp [IterM.forIn_eq]
· simp [IterM.forIn_eq]
· simp
theorem IterM.forM_eq_forIn {α β : Type w} {m : Type w → Type w'} [Iterator α m β]
[Finite α m] {n : Type w → Type w''} [Monad n] [LawfulMonad n]
[IteratorLoop α m n] [LawfulIteratorLoop α m n]
[MonadLiftT m n] {it : IterM (α := α) m β}
{f : β → n PUnit} :
ForM.forM it f = ForIn.forIn it PUnit.unit (fun out _ => do f out; return .yield .unit) :=
rfl
theorem IterM.forM_eq_match_step {α β : Type w} {m : Type w → Type w'} [Iterator α m β]
[Finite α m] {n : Type w → Type w''} [Monad n] [LawfulMonad n]
[IteratorLoop α m n] [LawfulIteratorLoop α m n]
[MonadLiftT m n] {it : IterM (α := α) m β}
{f : β → n PUnit} :
ForM.forM it f = (do
match ← it.step with
| .yield it' out _ =>
f out
ForM.forM it' f
| .skip it' _ => ForM.forM it' f
| .done _ => return) := by
rw [forM_eq_forIn, forIn_eq_match_step]
apply bind_congr
intro step
cases step using PlausibleIterStep.casesOn <;> simp [forM_eq_forIn]
theorem IterM.foldM_eq_forIn {α β γ : Type w} {m : Type w → Type w'} [Iterator α m β] [Finite α m]
{n : Type w → Type w''} [Monad n] [IteratorLoop α m n] [MonadLiftT m n] {f : γ → β → n γ}
{init : γ} {it : IterM (α := α) m β} :
it.foldM (init := init) f = ForIn.forIn it init (fun x acc => ForInStep.yield <$> f acc x) :=
rfl
theorem IterM.forIn_yield_eq_foldM {α β γ δ : Type w} {m : Type w → Type w'} [Iterator α m β]
[Finite α m] {n : Type w → Type w''} [Monad n] [LawfulMonad n] [IteratorLoop α m n]
[LawfulIteratorLoop α m n] [MonadLiftT m n] {f : β → γ → n δ} {g : β → γ → δ → γ} {init : γ}
{it : IterM (α := α) m β} :
ForIn.forIn it init (fun c b => (fun d => .yield (g c b d)) <$> f c b) =
it.foldM (fun b c => g c b <$> f c b) init := by
simp [IterM.foldM_eq_forIn]
theorem IterM.foldM_eq_match_step {α β γ : Type w} {m : Type w → Type w'} [Iterator α m β] [Finite α m]
{n : Type w → Type w''} [Monad n] [LawfulMonad n] [IteratorLoop α m n] [LawfulIteratorLoop α m n]
[MonadLiftT m n] {f : γ → β → n γ} {init : γ} {it : IterM (α := α) m β} :
it.foldM (init := init) f = (do
match ← it.step with
| .yield it' out _ => it'.foldM (init := ← f init out) f
| .skip it' _ => it'.foldM (init := init) f
| .done _ => return init) := by
rw [IterM.foldM_eq_forIn, IterM.forIn_eq_match_step]
apply bind_congr
intro step
cases step using PlausibleIterStep.casesOn <;> simp [foldM_eq_forIn]
theorem IterM.fold_eq_forIn {α β γ : Type w} {m : Type w → Type w'} [Iterator α m β]
[Finite α m] [Monad m]
[IteratorLoop α m m] {f : γ → β → γ} {init : γ} {it : IterM (α := α) m β} :
it.fold (init := init) f =
ForIn.forIn (m := m) it init (fun x acc => pure (ForInStep.yield (f acc x))) := by
rfl
theorem IterM.fold_eq_foldM {α β γ : Type w} {m : Type w → Type w'} [Iterator α m β]
[Finite α m] [Monad m] [LawfulMonad m] [IteratorLoop α m m] {f : γ → β → γ} {init : γ}
{it : IterM (α := α) m β} :
it.fold (init := init) f = it.foldM (init := init) (pure <| f · ·) := by
simp [foldM_eq_forIn, fold_eq_forIn]
@[simp]
theorem IterM.forIn_pure_yield_eq_fold {α β γ : Type w} {m : Type w → Type w'} [Iterator α m β]
[Finite α m] [Monad m] [LawfulMonad m] [IteratorLoop α m m]
[LawfulIteratorLoop α m m] {f : β → γγ} {init : γ}
{it : IterM (α := α) m β} :
ForIn.forIn it init (fun c b => pure (.yield (f c b))) =
it.fold (fun b c => f c b) init := by
simp [IterM.fold_eq_forIn]
theorem IterM.fold_eq_match_step {α β γ : Type w} {m : Type w → Type w'} [Iterator α m β] [Finite α m]
[Monad m] [LawfulMonad m] [IteratorLoop α m m] [LawfulIteratorLoop α m m]
{f : γ → β → γ} {init : γ} {it : IterM (α := α) m β} :
it.fold (init := init) f = (do
match ← it.step with
| .yield it' out _ => it'.fold (init := f init out) f
| .skip it' _ => it'.fold (init := init) f
| .done _ => return init) := by
rw [fold_eq_foldM, foldM_eq_match_step]
simp only [fold_eq_foldM]
apply bind_congr
intro step
cases step using PlausibleIterStep.casesOn <;> simp
theorem IterM.toList_eq_fold {α β : Type w} {m : Type w → Type w'} [Iterator α m β]
[Finite α m] [Monad m] [LawfulMonad m] [IteratorLoop α m m] [LawfulIteratorLoop α m m]
[IteratorCollect α m m] [LawfulIteratorCollect α m m]
{it : IterM (α := α) m β} :
it.toList = it.fold (init := []) (fun l out => l ++ [out]) := by
suffices h : ∀ l' : List β, (l' ++ ·) <$> it.toList =
it.fold (init := l') (fun l out => l ++ [out]) by
specialize h []
simpa using h
induction it using IterM.inductSteps with | step it ihy ihs =>
intro l'
rw [IterM.toList_eq_match_step, IterM.fold_eq_match_step]
simp only [map_eq_pure_bind, bind_assoc]
apply bind_congr
intro step
cases step using PlausibleIterStep.casesOn
· rename_i it' out h
specialize ihy h (l' ++ [out])
simpa using ihy
· rename_i it' h
simp [ihs h]
· simp
theorem IterM.drain_eq_fold {α β : Type w} {m : Type w → Type w'} [Iterator α m β] [Finite α m]
[Monad m] [IteratorLoop α m m] {it : IterM (α := α) m β} :
it.drain = it.fold (init := PUnit.unit) (fun _ _ => .unit) :=
rfl
theorem IterM.drain_eq_foldM {α β : Type w} {m : Type w → Type w'} [Iterator α m β] [Finite α m]
[Monad m] [LawfulMonad m] [IteratorLoop α m m] {it : IterM (α := α) m β} :
it.drain = it.foldM (init := PUnit.unit) (fun _ _ => pure .unit) := by
simp [IterM.drain_eq_fold, IterM.fold_eq_foldM]
theorem IterM.drain_eq_forIn {α β : Type w} {m : Type w → Type w'} [Iterator α m β] [Finite α m]
[Monad m] [IteratorLoop α m m] {it : IterM (α := α) m β} :
it.drain = ForIn.forIn (m := m) it PUnit.unit (fun _ _ => pure (ForInStep.yield .unit)) := by
simp [IterM.drain_eq_fold, IterM.fold_eq_forIn]
theorem IterM.drain_eq_match_step {α β : Type w} {m : Type w → Type w'} [Iterator α m β] [Finite α m]
[Monad m] [LawfulMonad m] [IteratorLoop α m m] [LawfulIteratorLoop α m m]
{it : IterM (α := α) m β} :
it.drain = (do
match ← it.step with
| .yield it' _ _ => it'.drain
| .skip it' _ => it'.drain
| .done _ => return .unit) := by
rw [IterM.drain_eq_fold, IterM.fold_eq_match_step]
simp [IterM.drain_eq_fold]
theorem IterM.drain_eq_map_toList {α β : Type w} {m : Type w → Type w'} [Iterator α m β]
[Finite α m] [Monad m] [LawfulMonad m] [IteratorLoop α m m] [LawfulIteratorLoop α m m]
[IteratorCollect α m m] [LawfulIteratorCollect α m m]
{it : IterM (α := α) m β} :
it.drain = (fun _ => .unit) <$> it.toList := by
induction it using IterM.inductSteps with | step it ihy ihs =>
rw [IterM.drain_eq_match_step, IterM.toList_eq_match_step]
simp only [map_eq_pure_bind, bind_assoc]
apply bind_congr
intro step
cases step using PlausibleIterStep.casesOn
· rename_i it' out h
simp [ihy h]
· rename_i it' h
simp [ihs h]
· simp
theorem IterM.drain_eq_map_toListRev {α β : Type w} {m : Type w → Type w'} [Iterator α m β]
[Finite α m] [Monad m] [LawfulMonad m] [IteratorLoop α m m] [LawfulIteratorLoop α m m]
[IteratorCollect α m m] [LawfulIteratorCollect α m m]
{it : IterM (α := α) m β} :
it.drain = (fun _ => .unit) <$> it.toListRev := by
simp [IterM.drain_eq_map_toList, IterM.toListRev_eq]
theorem IterM.drain_eq_map_toArray {α β : Type w} {m : Type w → Type w'} [Iterator α m β]
[Finite α m] [Monad m] [LawfulMonad m] [IteratorLoop α m m] [LawfulIteratorLoop α m m]
[IteratorCollect α m m] [LawfulIteratorCollect α m m]
{it : IterM (α := α) m β} :
it.drain = (fun _ => .unit) <$> it.toList := by
simp [IterM.drain_eq_map_toList]
section Equivalence
theorem IterM.Equiv.forIn_eq {α₁ α₂ β γ : Type w} {m : Type w → Type w'}
{n : Type w → Type w''} [Iterator α₁ m β] [Iterator α₂ m β]
[Finite α₁ m] [Finite α₂ m]
@ -296,6 +74,4 @@ theorem IterM.Equiv.drain_eq {α₁ α₂ β : Type w} {m : Type w → Type w'}
ita.drain = itb.drain := by
simp [IterM.drain_eq_fold, h.fold_eq]
end Equivalence
end Std.Iterators

View file

@ -8,8 +8,8 @@ import Init.Control.Lawful.Basic
import Init.Ext
import Init.Internal.Order
import Init.Core
import Std.Data.Iterators.Basic
import Std.Data.Iterators.PostConditionMonad
import Init.Data.Iterators.Basic
import Init.Data.Iterators.PostconditionMonad
import Std.Data.Iterators.Lemmas.Equivalence.HetT
namespace Std.Iterators

View file

@ -8,8 +8,8 @@ import Init.Control.Lawful.Basic
import Init.Data.Subtype
import Init.PropLemmas
import Init.Classical
import Std.Data.Internal.LawfulMonadLiftFunction
import Std.Data.Iterators.PostConditionMonad
import Init.Data.Iterators.Internal.LawfulMonadLiftFunction
import Init.Data.Iterators.PostconditionMonad
namespace Std.Internal

View file

@ -4,4 +4,4 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Paul Reichert
-/
prelude
import Std.Data.Iterators.Lemmas.Monadic.Basic
import Init.Data.Iterators.Lemmas.Monadic.Basic

View file

@ -5,6 +5,8 @@ Authors: Paul Reichert
-/
prelude
import Std.Data.Iterators.Lemmas.Consumers.Collect
import Std.Data.Iterators.Producers.Array
import Std.Data.Iterators.Producers.List
import Std.Data.Iterators.Lemmas.Producers.Monadic.Array
/-!

View file

@ -5,7 +5,7 @@ Authors: Paul Reichert
-/
prelude
import Std.Data.Iterators.Lemmas.Producers.Monadic.Empty
import Std.Data.Iterators.Lemmas.Consumers
import Init.Data.Iterators.Lemmas.Consumers
import Std.Data.Iterators.Producers.Empty
namespace Std.Iterators

View file

@ -4,8 +4,9 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Paul Reichert
-/
prelude
import Std.Data.Iterators.Consumers
import Std.Data.Iterators.Lemmas.Consumers.Collect
import Init.Data.Iterators.Consumers
import Init.Data.Iterators.Lemmas.Consumers.Collect
import Std.Data.Iterators.Producers.List
import Std.Data.Iterators.Lemmas.Producers.Monadic.List
/-!

View file

@ -4,9 +4,9 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Paul Reichert
-/
prelude
import Std.Data.Internal.LawfulMonadLiftFunction
import Init.Data.Iterators.Internal.LawfulMonadLiftFunction
import Init.Data.Iterators.Consumers
import Std.Data.Iterators.Producers.Monadic.Array
import Std.Data.Iterators.Consumers
import Std.Data.Iterators.Lemmas.Consumers.Monadic
import Std.Data.Iterators.Lemmas.Producers.Monadic.List
import Std.Data.Iterators.Lemmas.Equivalence.Basic

View file

@ -5,8 +5,8 @@ Authors: Paul Reichert
-/
prelude
import Std.Data.Iterators.Producers.Monadic.Empty
import Std.Data.Iterators.Lemmas.Consumers.Monadic
import Std.Data.Iterators.Lemmas.Consumers.Monadic.Loop
import Init.Data.Iterators.Lemmas.Consumers.Monadic
import Init.Data.Iterators.Lemmas.Consumers.Monadic.Loop
namespace Std.Iterators

View file

@ -4,10 +4,11 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Paul Reichert
-/
prelude
import Init.Data.Iterators.Consumers
import Init.Data.Iterators.Lemmas.Consumers.Monadic
import Init.Data.Iterators.Internal.LawfulMonadLiftFunction
import Std.Data.Iterators.Producers.Monadic.List
import Std.Data.Iterators.Consumers
import Std.Data.Iterators.Lemmas.Consumers.Monadic
import Std.Data.Internal.LawfulMonadLiftFunction
import Std.Data.Iterators.Lemmas.Equivalence.Basic
/-!
# Lemmas about list iterators

View file

@ -6,8 +6,8 @@ Authors: Paul Reichert
prelude
import Init.Data.Option.Lemmas
import Std.Data.Iterators.Producers.Repeat
import Std.Data.Iterators.Consumers.Access
import Std.Data.Iterators.Consumers.Collect
import Init.Data.Iterators.Consumers.Access
import Init.Data.Iterators.Consumers.Collect
import Std.Data.Iterators.Combinators.Take
import Std.Data.Iterators.Lemmas.Combinators.Take

View file

@ -6,8 +6,8 @@ Authors: Paul Reichert
prelude
import Init.Data.Nat.Lemmas
import Init.RCases
import Std.Data.Iterators.Consumers
import Std.Data.Iterators.Internal.Termination
import Init.Data.Iterators.Consumers
import Init.Data.Iterators.Internal.Termination
/-!
# Array iterator

View file

@ -4,9 +4,9 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Paul Reichert
-/
prelude
import Std.Data.Iterators.Consumers.Collect
import Std.Data.Iterators.Consumers.Loop
import Std.Data.Iterators.Internal.Termination
import Init.Data.Iterators.Consumers.Collect
import Init.Data.Iterators.Consumers.Loop
import Init.Data.Iterators.Internal.Termination
/-!
This file provides an empty iterator.

View file

@ -6,8 +6,8 @@ Authors: Paul Reichert
prelude
import Init.Data.Nat.Lemmas
import Init.RCases
import Std.Data.Iterators.Consumers
import Std.Data.Iterators.Internal.Termination
import Init.Data.Iterators.Consumers
import Init.Data.Iterators.Internal.Termination
/-!
# List iterator

View file

@ -4,8 +4,8 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Paul Reichert
-/
prelude
import Std.Data.Iterators.Consumers.Monadic
import Std.Data.Iterators.Internal.Termination
import Init.Data.Iterators.Consumers.Monadic
import Init.Data.Iterators.Internal.Termination
/-!
# Function-unfolding iterator