diff --git a/src/Init/Data.lean b/src/Init/Data.lean index 4b571eae65..6028db89a3 100644 --- a/src/Init/Data.lean +++ b/src/Init/Data.lean @@ -46,3 +46,4 @@ import Init.Data.NeZero import Init.Data.Function import Init.Data.RArray import Init.Data.Vector +import Init.Data.Iterators diff --git a/src/Init/Data/Iterators.lean b/src/Init/Data/Iterators.lean new file mode 100644 index 0000000000..115a534b45 --- /dev/null +++ b/src/Init/Data/Iterators.lean @@ -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. +-/ diff --git a/src/Std/Data/Iterators/Basic.lean b/src/Init/Data/Iterators/Basic.lean similarity index 95% rename from src/Std/Data/Iterators/Basic.lean rename to src/Init/Data/Iterators/Basic.lean index 7890bbb313..cafea31f0f 100644 --- a/src/Std/Data/Iterators/Basic.lean +++ b/src/Init/Data/Iterators/Basic.lean @@ -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 diff --git a/src/Init/Data/Iterators/Consumers.lean b/src/Init/Data/Iterators/Consumers.lean new file mode 100644 index 0000000000..e61fab7a94 --- /dev/null +++ b/src/Init/Data/Iterators/Consumers.lean @@ -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 diff --git a/src/Std/Data/Iterators/Consumers/Access.lean b/src/Init/Data/Iterators/Consumers/Access.lean similarity index 97% rename from src/Std/Data/Iterators/Consumers/Access.lean rename to src/Init/Data/Iterators/Consumers/Access.lean index a4a675e5a0..65173c3402 100644 --- a/src/Std/Data/Iterators/Consumers/Access.lean +++ b/src/Init/Data/Iterators/Consumers/Access.lean @@ -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 diff --git a/src/Std/Data/Iterators/Consumers/Collect.lean b/src/Init/Data/Iterators/Consumers/Collect.lean similarity index 93% rename from src/Std/Data/Iterators/Consumers/Collect.lean rename to src/Init/Data/Iterators/Consumers/Collect.lean index 4e21f8f21b..fd848dfd55 100644 --- a/src/Std/Data/Iterators/Consumers/Collect.lean +++ b/src/Init/Data/Iterators/Consumers/Collect.lean @@ -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 diff --git a/src/Std/Data/Iterators/Consumers/Loop.lean b/src/Init/Data/Iterators/Consumers/Loop.lean similarity index 97% rename from src/Std/Data/Iterators/Consumers/Loop.lean rename to src/Init/Data/Iterators/Consumers/Loop.lean index 35bc0e095a..893ffe6116 100644 --- a/src/Std/Data/Iterators/Consumers/Loop.lean +++ b/src/Init/Data/Iterators/Consumers/Loop.lean @@ -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 diff --git a/src/Init/Data/Iterators/Consumers/Monadic.lean b/src/Init/Data/Iterators/Consumers/Monadic.lean new file mode 100644 index 0000000000..c47ed1f435 --- /dev/null +++ b/src/Init/Data/Iterators/Consumers/Monadic.lean @@ -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 diff --git a/src/Std/Data/Iterators/Consumers/Monadic/Collect.lean b/src/Init/Data/Iterators/Consumers/Monadic/Collect.lean similarity index 98% rename from src/Std/Data/Iterators/Consumers/Monadic/Collect.lean rename to src/Init/Data/Iterators/Consumers/Monadic/Collect.lean index 226513ab88..e0e714943c 100644 --- a/src/Std/Data/Iterators/Consumers/Monadic/Collect.lean +++ b/src/Init/Data/Iterators/Consumers/Monadic/Collect.lean @@ -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 diff --git a/src/Std/Data/Iterators/Consumers/Monadic/Loop.lean b/src/Init/Data/Iterators/Consumers/Monadic/Loop.lean similarity index 93% rename from src/Std/Data/Iterators/Consumers/Monadic/Loop.lean rename to src/Init/Data/Iterators/Consumers/Monadic/Loop.lean index 7aefb897a3..650629ed14 100644 --- a/src/Std/Data/Iterators/Consumers/Monadic/Loop.lean +++ b/src/Init/Data/Iterators/Consumers/Monadic/Loop.lean @@ -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] : diff --git a/src/Std/Data/Iterators/Consumers/Monadic/Partial.lean b/src/Init/Data/Iterators/Consumers/Monadic/Partial.lean similarity index 95% rename from src/Std/Data/Iterators/Consumers/Monadic/Partial.lean rename to src/Init/Data/Iterators/Consumers/Monadic/Partial.lean index 0729615bdc..5f87ab2cb5 100644 --- a/src/Std/Data/Iterators/Consumers/Monadic/Partial.lean +++ b/src/Init/Data/Iterators/Consumers/Monadic/Partial.lean @@ -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 diff --git a/src/Std/Data/Iterators/Consumers/Partial.lean b/src/Init/Data/Iterators/Consumers/Partial.lean similarity index 95% rename from src/Std/Data/Iterators/Consumers/Partial.lean rename to src/Init/Data/Iterators/Consumers/Partial.lean index 2d16d5b93a..2823d318b2 100644 --- a/src/Std/Data/Iterators/Consumers/Partial.lean +++ b/src/Init/Data/Iterators/Consumers/Partial.lean @@ -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 diff --git a/src/Init/Data/Iterators/Internal.lean b/src/Init/Data/Iterators/Internal.lean new file mode 100644 index 0000000000..2728123f13 --- /dev/null +++ b/src/Init/Data/Iterators/Internal.lean @@ -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 diff --git a/src/Std/Data/Internal/LawfulMonadLiftFunction.lean b/src/Init/Data/Iterators/Internal/LawfulMonadLiftFunction.lean similarity index 99% rename from src/Std/Data/Internal/LawfulMonadLiftFunction.lean rename to src/Init/Data/Iterators/Internal/LawfulMonadLiftFunction.lean index 28508c7d6a..b011065a5c 100644 --- a/src/Std/Data/Internal/LawfulMonadLiftFunction.lean +++ b/src/Init/Data/Iterators/Internal/LawfulMonadLiftFunction.lean @@ -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 diff --git a/src/Std/Data/Iterators/Internal/Termination.lean b/src/Init/Data/Iterators/Internal/Termination.lean similarity index 97% rename from src/Std/Data/Iterators/Internal/Termination.lean rename to src/Init/Data/Iterators/Internal/Termination.lean index 7da422b1d0..0229464884 100644 --- a/src/Std/Data/Iterators/Internal/Termination.lean +++ b/src/Init/Data/Iterators/Internal/Termination.lean @@ -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. diff --git a/src/Std/Data/Iterators/Internal.lean b/src/Init/Data/Iterators/Lemmas.lean similarity index 75% rename from src/Std/Data/Iterators/Internal.lean rename to src/Init/Data/Iterators/Lemmas.lean index aa5ab7f1cd..65a041ee83 100644 --- a/src/Std/Data/Iterators/Internal.lean +++ b/src/Init/Data/Iterators/Lemmas.lean @@ -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 diff --git a/src/Std/Data/Iterators/Lemmas/Basic.lean b/src/Init/Data/Iterators/Lemmas/Basic.lean similarity index 97% rename from src/Std/Data/Iterators/Lemmas/Basic.lean rename to src/Init/Data/Iterators/Lemmas/Basic.lean index f9f208f025..dc8733e83d 100644 --- a/src/Std/Data/Iterators/Lemmas/Basic.lean +++ b/src/Init/Data/Iterators/Lemmas/Basic.lean @@ -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 diff --git a/src/Init/Data/Iterators/Lemmas/Consumers.lean b/src/Init/Data/Iterators/Lemmas/Consumers.lean new file mode 100644 index 0000000000..a363ee747f --- /dev/null +++ b/src/Init/Data/Iterators/Lemmas/Consumers.lean @@ -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 diff --git a/src/Init/Data/Iterators/Lemmas/Consumers/Collect.lean b/src/Init/Data/Iterators/Lemmas/Consumers/Collect.lean new file mode 100644 index 0000000000..cb257f54ba --- /dev/null +++ b/src/Init/Data/Iterators/Lemmas/Consumers/Collect.lean @@ -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 diff --git a/src/Init/Data/Iterators/Lemmas/Consumers/Loop.lean b/src/Init/Data/Iterators/Lemmas/Consumers/Loop.lean new file mode 100644 index 0000000000..27faae68e8 --- /dev/null +++ b/src/Init/Data/Iterators/Lemmas/Consumers/Loop.lean @@ -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 diff --git a/src/Std/Data/Iterators/Consumers/Monadic.lean b/src/Init/Data/Iterators/Lemmas/Consumers/Monadic.lean similarity index 51% rename from src/Std/Data/Iterators/Consumers/Monadic.lean rename to src/Init/Data/Iterators/Lemmas/Consumers/Monadic.lean index 6e861afb81..bcbc5fd29f 100644 --- a/src/Std/Data/Iterators/Consumers/Monadic.lean +++ b/src/Init/Data/Iterators/Lemmas/Consumers/Monadic.lean @@ -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 diff --git a/src/Init/Data/Iterators/Lemmas/Consumers/Monadic/Collect.lean b/src/Init/Data/Iterators/Lemmas/Consumers/Monadic/Collect.lean new file mode 100644 index 0000000000..7f45f163c0 --- /dev/null +++ b/src/Init/Data/Iterators/Lemmas/Consumers/Monadic/Collect.lean @@ -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 diff --git a/src/Init/Data/Iterators/Lemmas/Consumers/Monadic/Loop.lean b/src/Init/Data/Iterators/Lemmas/Consumers/Monadic/Loop.lean new file mode 100644 index 0000000000..e594b61fab --- /dev/null +++ b/src/Init/Data/Iterators/Lemmas/Consumers/Monadic/Loop.lean @@ -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 diff --git a/src/Std/Data/Iterators/Lemmas/Monadic/Basic.lean b/src/Init/Data/Iterators/Lemmas/Monadic/Basic.lean similarity index 97% rename from src/Std/Data/Iterators/Lemmas/Monadic/Basic.lean rename to src/Init/Data/Iterators/Lemmas/Monadic/Basic.lean index cabd7e96ef..3753c26f9d 100644 --- a/src/Std/Data/Iterators/Lemmas/Monadic/Basic.lean +++ b/src/Init/Data/Iterators/Lemmas/Monadic/Basic.lean @@ -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 diff --git a/src/Std/Data/Iterators/PostConditionMonad.lean b/src/Init/Data/Iterators/PostconditionMonad.lean similarity index 90% rename from src/Std/Data/Iterators/PostConditionMonad.lean rename to src/Init/Data/Iterators/PostconditionMonad.lean index 245b10b5ca..eca755026a 100644 --- a/src/Std/Data/Iterators/PostConditionMonad.lean +++ b/src/Init/Data/Iterators/PostconditionMonad.lean @@ -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 diff --git a/src/Std/Data/Iterators.lean b/src/Std/Data/Iterators.lean index 2e4c17e3bb..2aa9f61c6a 100644 --- a/src/Std/Data/Iterators.lean +++ b/src/Std/Data/Iterators.lean @@ -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 diff --git a/src/Std/Data/Iterators/Combinators/Monadic/Drop.lean b/src/Std/Data/Iterators/Combinators/Monadic/Drop.lean index 3297883175..856ec7724c 100644 --- a/src/Std/Data/Iterators/Combinators/Monadic/Drop.lean +++ b/src/Std/Data/Iterators/Combinators/Monadic/Drop.lean @@ -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`. diff --git a/src/Std/Data/Iterators/Combinators/Monadic/DropWhile.lean b/src/Std/Data/Iterators/Combinators/Monadic/DropWhile.lean index 1ce9df4516..32c5d15cd8 100644 --- a/src/Std/Data/Iterators/Combinators/Monadic/DropWhile.lean +++ b/src/Std/Data/Iterators/Combinators/Monadic/DropWhile.lean @@ -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 diff --git a/src/Std/Data/Iterators/Combinators/Monadic/FilterMap.lean b/src/Std/Data/Iterators/Combinators/Monadic/FilterMap.lean index c309fa3148..8e3ccacc86 100644 --- a/src/Std/Data/Iterators/Combinators/Monadic/FilterMap.lean +++ b/src/Std/Data/Iterators/Combinators/Monadic/FilterMap.lean @@ -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 /-! diff --git a/src/Std/Data/Iterators/Combinators/Monadic/Take.lean b/src/Std/Data/Iterators/Combinators/Monadic/Take.lean index 19d5675faf..e0b1232d79 100644 --- a/src/Std/Data/Iterators/Combinators/Monadic/Take.lean +++ b/src/Std/Data/Iterators/Combinators/Monadic/Take.lean @@ -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 diff --git a/src/Std/Data/Iterators/Combinators/Monadic/TakeWhile.lean b/src/Std/Data/Iterators/Combinators/Monadic/TakeWhile.lean index 4b19fe458d..9d2dab13ad 100644 --- a/src/Std/Data/Iterators/Combinators/Monadic/TakeWhile.lean +++ b/src/Std/Data/Iterators/Combinators/Monadic/TakeWhile.lean @@ -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 diff --git a/src/Std/Data/Iterators/Combinators/Monadic/Zip.lean b/src/Std/Data/Iterators/Combinators/Monadic/Zip.lean index 1105ab1a12..9fa557280e 100644 --- a/src/Std/Data/Iterators/Combinators/Monadic/Zip.lean +++ b/src/Std/Data/Iterators/Combinators/Monadic/Zip.lean @@ -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 /-! diff --git a/src/Std/Data/Iterators/Consumers.lean b/src/Std/Data/Iterators/Consumers.lean deleted file mode 100644 index f835cc73e8..0000000000 --- a/src/Std/Data/Iterators/Consumers.lean +++ /dev/null @@ -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 diff --git a/src/Std/Data/Iterators/Lemmas.lean b/src/Std/Data/Iterators/Lemmas.lean index 834c639833..927b232152 100644 --- a/src/Std/Data/Iterators/Lemmas.lean +++ b/src/Std/Data/Iterators/Lemmas.lean @@ -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 diff --git a/src/Std/Data/Iterators/Lemmas/Combinators/Drop.lean b/src/Std/Data/Iterators/Lemmas/Combinators/Drop.lean index d17200b2c9..235089465b 100644 --- a/src/Std/Data/Iterators/Lemmas/Combinators/Drop.lean +++ b/src/Std/Data/Iterators/Lemmas/Combinators/Drop.lean @@ -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 diff --git a/src/Std/Data/Iterators/Lemmas/Combinators/DropWhile.lean b/src/Std/Data/Iterators/Lemmas/Combinators/DropWhile.lean index eddbf2203c..0eb19541e8 100644 --- a/src/Std/Data/Iterators/Lemmas/Combinators/DropWhile.lean +++ b/src/Std/Data/Iterators/Lemmas/Combinators/DropWhile.lean @@ -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 diff --git a/src/Std/Data/Iterators/Lemmas/Combinators/FilterMap.lean b/src/Std/Data/Iterators/Lemmas/Combinators/FilterMap.lean index 0042dc9127..d987a71d82 100644 --- a/src/Std/Data/Iterators/Lemmas/Combinators/FilterMap.lean +++ b/src/Std/Data/Iterators/Lemmas/Combinators/FilterMap.lean @@ -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 diff --git a/src/Std/Data/Iterators/Lemmas/Combinators/Monadic/Drop.lean b/src/Std/Data/Iterators/Lemmas/Combinators/Monadic/Drop.lean index f52ab64a48..afd4a6b8a6 100644 --- a/src/Std/Data/Iterators/Lemmas/Combinators/Monadic/Drop.lean +++ b/src/Std/Data/Iterators/Lemmas/Combinators/Monadic/Drop.lean @@ -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 diff --git a/src/Std/Data/Iterators/Lemmas/Combinators/Monadic/DropWhile.lean b/src/Std/Data/Iterators/Lemmas/Combinators/Monadic/DropWhile.lean index 0585fbdcf4..f342319918 100644 --- a/src/Std/Data/Iterators/Lemmas/Combinators/Monadic/DropWhile.lean +++ b/src/Std/Data/Iterators/Lemmas/Combinators/Monadic/DropWhile.lean @@ -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 diff --git a/src/Std/Data/Iterators/Lemmas/Combinators/Monadic/FilterMap.lean b/src/Std/Data/Iterators/Lemmas/Combinators/Monadic/FilterMap.lean index c709df1303..c6d68f8c8c 100644 --- a/src/Std/Data/Iterators/Lemmas/Combinators/Monadic/FilterMap.lean +++ b/src/Std/Data/Iterators/Lemmas/Combinators/Monadic/FilterMap.lean @@ -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 diff --git a/src/Std/Data/Iterators/Lemmas/Combinators/Monadic/Take.lean b/src/Std/Data/Iterators/Lemmas/Combinators/Monadic/Take.lean index 8d272a4470..1de5394ddc 100644 --- a/src/Std/Data/Iterators/Lemmas/Combinators/Monadic/Take.lean +++ b/src/Std/Data/Iterators/Lemmas/Combinators/Monadic/Take.lean @@ -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 diff --git a/src/Std/Data/Iterators/Lemmas/Combinators/Monadic/Zip.lean b/src/Std/Data/Iterators/Lemmas/Combinators/Monadic/Zip.lean index b438ee5835..e4aa6d1c50 100644 --- a/src/Std/Data/Iterators/Lemmas/Combinators/Monadic/Zip.lean +++ b/src/Std/Data/Iterators/Lemmas/Combinators/Monadic/Zip.lean @@ -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 diff --git a/src/Std/Data/Iterators/Lemmas/Combinators/Take.lean b/src/Std/Data/Iterators/Lemmas/Combinators/Take.lean index aacd6f29a1..1e039d97ea 100644 --- a/src/Std/Data/Iterators/Lemmas/Combinators/Take.lean +++ b/src/Std/Data/Iterators/Lemmas/Combinators/Take.lean @@ -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 diff --git a/src/Std/Data/Iterators/Lemmas/Combinators/Zip.lean b/src/Std/Data/Iterators/Lemmas/Combinators/Zip.lean index 083fc5e93a..b4365f0944 100644 --- a/src/Std/Data/Iterators/Lemmas/Combinators/Zip.lean +++ b/src/Std/Data/Iterators/Lemmas/Combinators/Zip.lean @@ -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 diff --git a/src/Std/Data/Iterators/Lemmas/Consumers/Collect.lean b/src/Std/Data/Iterators/Lemmas/Consumers/Collect.lean index bd8be165ff..4092746fac 100644 --- a/src/Std/Data/Iterators/Lemmas/Consumers/Collect.lean +++ b/src/Std/Data/Iterators/Lemmas/Consumers/Collect.lean @@ -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 diff --git a/src/Std/Data/Iterators/Lemmas/Consumers/Loop.lean b/src/Std/Data/Iterators/Lemmas/Consumers/Loop.lean index 8ed9231bd8..ee8f60d087 100644 --- a/src/Std/Data/Iterators/Lemmas/Consumers/Loop.lean +++ b/src/Std/Data/Iterators/Lemmas/Consumers/Loop.lean @@ -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 diff --git a/src/Std/Data/Iterators/Lemmas/Consumers/Monadic/Collect.lean b/src/Std/Data/Iterators/Lemmas/Consumers/Monadic/Collect.lean index a65a445be8..d67cd59dbf 100644 --- a/src/Std/Data/Iterators/Lemmas/Consumers/Monadic/Collect.lean +++ b/src/Std/Data/Iterators/Lemmas/Consumers/Monadic/Collect.lean @@ -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 diff --git a/src/Std/Data/Iterators/Lemmas/Consumers/Monadic/Loop.lean b/src/Std/Data/Iterators/Lemmas/Consumers/Monadic/Loop.lean index 2c11ec412a..0aee0d3df0 100644 --- a/src/Std/Data/Iterators/Lemmas/Consumers/Monadic/Loop.lean +++ b/src/Std/Data/Iterators/Lemmas/Consumers/Monadic/Loop.lean @@ -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 diff --git a/src/Std/Data/Iterators/Lemmas/Equivalence/Basic.lean b/src/Std/Data/Iterators/Lemmas/Equivalence/Basic.lean index 5700aa193d..b3574daff4 100644 --- a/src/Std/Data/Iterators/Lemmas/Equivalence/Basic.lean +++ b/src/Std/Data/Iterators/Lemmas/Equivalence/Basic.lean @@ -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 diff --git a/src/Std/Data/Iterators/Lemmas/Equivalence/HetT.lean b/src/Std/Data/Iterators/Lemmas/Equivalence/HetT.lean index 0ecfd32421..ce00751a82 100644 --- a/src/Std/Data/Iterators/Lemmas/Equivalence/HetT.lean +++ b/src/Std/Data/Iterators/Lemmas/Equivalence/HetT.lean @@ -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 diff --git a/src/Std/Data/Iterators/Lemmas/Monadic.lean b/src/Std/Data/Iterators/Lemmas/Monadic.lean index daa55f5fa5..cbaa515388 100644 --- a/src/Std/Data/Iterators/Lemmas/Monadic.lean +++ b/src/Std/Data/Iterators/Lemmas/Monadic.lean @@ -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 diff --git a/src/Std/Data/Iterators/Lemmas/Producers/Array.lean b/src/Std/Data/Iterators/Lemmas/Producers/Array.lean index f74f9d7a33..9e3f0c5692 100644 --- a/src/Std/Data/Iterators/Lemmas/Producers/Array.lean +++ b/src/Std/Data/Iterators/Lemmas/Producers/Array.lean @@ -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 /-! diff --git a/src/Std/Data/Iterators/Lemmas/Producers/Empty.lean b/src/Std/Data/Iterators/Lemmas/Producers/Empty.lean index e96a100d40..6649d9cb63 100644 --- a/src/Std/Data/Iterators/Lemmas/Producers/Empty.lean +++ b/src/Std/Data/Iterators/Lemmas/Producers/Empty.lean @@ -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 diff --git a/src/Std/Data/Iterators/Lemmas/Producers/List.lean b/src/Std/Data/Iterators/Lemmas/Producers/List.lean index e5d7b8a73f..af4adb5c8f 100644 --- a/src/Std/Data/Iterators/Lemmas/Producers/List.lean +++ b/src/Std/Data/Iterators/Lemmas/Producers/List.lean @@ -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 /-! diff --git a/src/Std/Data/Iterators/Lemmas/Producers/Monadic/Array.lean b/src/Std/Data/Iterators/Lemmas/Producers/Monadic/Array.lean index ba2b2d6d20..d84d4a70dd 100644 --- a/src/Std/Data/Iterators/Lemmas/Producers/Monadic/Array.lean +++ b/src/Std/Data/Iterators/Lemmas/Producers/Monadic/Array.lean @@ -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 diff --git a/src/Std/Data/Iterators/Lemmas/Producers/Monadic/Empty.lean b/src/Std/Data/Iterators/Lemmas/Producers/Monadic/Empty.lean index 9bded4fd6f..3e073171e1 100644 --- a/src/Std/Data/Iterators/Lemmas/Producers/Monadic/Empty.lean +++ b/src/Std/Data/Iterators/Lemmas/Producers/Monadic/Empty.lean @@ -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 diff --git a/src/Std/Data/Iterators/Lemmas/Producers/Monadic/List.lean b/src/Std/Data/Iterators/Lemmas/Producers/Monadic/List.lean index 8052bb745a..2b7873daae 100644 --- a/src/Std/Data/Iterators/Lemmas/Producers/Monadic/List.lean +++ b/src/Std/Data/Iterators/Lemmas/Producers/Monadic/List.lean @@ -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 diff --git a/src/Std/Data/Iterators/Lemmas/Producers/Repeat.lean b/src/Std/Data/Iterators/Lemmas/Producers/Repeat.lean index 9cbbdd16a3..92b0815934 100644 --- a/src/Std/Data/Iterators/Lemmas/Producers/Repeat.lean +++ b/src/Std/Data/Iterators/Lemmas/Producers/Repeat.lean @@ -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 diff --git a/src/Std/Data/Iterators/Producers/Monadic/Array.lean b/src/Std/Data/Iterators/Producers/Monadic/Array.lean index fb5a0d1d07..92621e86e0 100644 --- a/src/Std/Data/Iterators/Producers/Monadic/Array.lean +++ b/src/Std/Data/Iterators/Producers/Monadic/Array.lean @@ -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 diff --git a/src/Std/Data/Iterators/Producers/Monadic/Empty.lean b/src/Std/Data/Iterators/Producers/Monadic/Empty.lean index e952845e6c..83040e752e 100644 --- a/src/Std/Data/Iterators/Producers/Monadic/Empty.lean +++ b/src/Std/Data/Iterators/Producers/Monadic/Empty.lean @@ -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. diff --git a/src/Std/Data/Iterators/Producers/Monadic/List.lean b/src/Std/Data/Iterators/Producers/Monadic/List.lean index 8af61472ef..ec95f7b0a3 100644 --- a/src/Std/Data/Iterators/Producers/Monadic/List.lean +++ b/src/Std/Data/Iterators/Producers/Monadic/List.lean @@ -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 diff --git a/src/Std/Data/Iterators/Producers/Repeat.lean b/src/Std/Data/Iterators/Producers/Repeat.lean index 66231cebba..30b6884bef 100644 --- a/src/Std/Data/Iterators/Producers/Repeat.lean +++ b/src/Std/Data/Iterators/Producers/Repeat.lean @@ -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