lean4-htt/src/Init/Data/Range/Polymorphic/RangeIterator.lean
Paul Reichert f58999a7a6
refactor: use Shrink stub in the iterator framework (#10725)
This PR introduces a no-op version of `Shrink`, a type that should allow
shrinking small types into smaller universes given a proof that the type
is small enough, and uses it in the iterator library. Because this type
would require special compiler support, the current version is just a
wrapper around the inner type so that the wrapper is equivalent, but not
definitionally equivalent.

While `Shrink` is unable to shrink universes right now, but introducing
it now will allow us to generalize the universes in the iterator library
with fewer breaking changes as soon as an actual `Shrink` is possible.
2025-10-14 10:22:14 +00:00

1661 lines
65 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/-
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
public import Init.Data.Iterators.Internal.Termination
public import Init.Data.Iterators.Consumers.Access
public import Init.Data.Iterators.Consumers.Loop
public import Init.Data.Iterators.Consumers.Collect
public import Init.Data.Range.Polymorphic.PRange
public import Init.Data.List.Sublist
set_option doc.verso true
public section
/-!
# Range iterator
This module implements an iterator for ranges (such as {name}`Std.Rcc`).
This iterator is publicly available via
{name (scope := "Std.Data.Iterators.Producers.Range")}`Std.Rcc.iter` (and identically named
functions in the sibling namespaces) after importing {lit}`Std.Data.Iterators`.
It powers many functions on ranges internally, such as
{name (scope := "Init.Data.Range.Polymorphic.Iterators")}`Rcc.toList`.
-/
open Std.Iterators
namespace Std
open PRange
namespace Rxc
variable {α : Type u} {lo hi a : α}
/-- Internal state of the range iterators. Do not depend on its internals. -/
@[unbox]
protected structure Iterator (α : Type u) where
next : Option α
upperBound : α
/--
The pure function mapping a range iterator of type {name}`IterM` to the next step of the iterator.
This function is prefixed with {lit}`Monadic` in order to disambiguate it from the version for
iterators of type {name}`Iter`.
-/
@[inline]
def Iterator.Monadic.step [UpwardEnumerable α] [LE α] [DecidableLE α]
(it : IterM (α := Rxc.Iterator α) Id α) :
IterStep (IterM (α := Rxc.Iterator α) Id α) α :=
match it.internalState.next with
| none => .done
| some next =>
if next ≤ it.internalState.upperBound then
.yield ⟨⟨UpwardEnumerable.succ? next, it.internalState.upperBound⟩⟩ next
else
.done
/--
The pure function mapping a range iterator of type {name}`Iter` to the next step of the iterator.
-/
@[always_inline, inline]
def Iterator.step [UpwardEnumerable α] [LE α] [DecidableLE α]
(it : Iter (α := Rxc.Iterator α) α) :
IterStep (Iter (α := Rxc.Iterator α) α) α :=
match it.internalState.next with
| none => .done
| some next => if next ≤ it.internalState.upperBound then
.yield ⟨⟨UpwardEnumerable.succ? next, it.internalState.upperBound⟩⟩ next
else
.done
theorem Iterator.step_eq_monadicStep [UpwardEnumerable α] [LE α] [DecidableLE α]
{it : Iter (α := Rxc.Iterator α) α} :
Iterator.step it = (Iterator.Monadic.step it.toIterM).mapIterator IterM.toIter := by
simp only [step, Monadic.step, Iter.toIterM]
split
· rfl
· split <;> rfl
@[always_inline, inline]
instance [UpwardEnumerable α] [LE α] [DecidableLE α] :
Iterator (Rxc.Iterator α) Id α where
IsPlausibleStep it step := step = Iterator.Monadic.step it
step it := pure <| .deflate <| ⟨Iterator.Monadic.step it, rfl⟩
theorem Iterator.Monadic.isPlausibleStep_iff [UpwardEnumerable α] [LE α] [DecidableLE α]
{it : IterM (α := Rxc.Iterator α) Id α} {step} :
it.IsPlausibleStep step ↔ step = Iterator.Monadic.step it := by
exact Iff.rfl
theorem Iterator.Monadic.step_eq_step [UpwardEnumerable α] [LE α] [DecidableLE α]
{it : IterM (α := Rxc.Iterator α) Id α} :
it.step = pure (.deflate ⟨Iterator.Monadic.step it, isPlausibleStep_iff.mpr rfl⟩) := by
simp [IterM.step, Iterators.Iterator.step]
theorem Iterator.isPlausibleStep_iff [UpwardEnumerable α] [LE α] [DecidableLE α]
{it : Iter (α := Rxc.Iterator α) α} {step} :
it.IsPlausibleStep step ↔ step = Iterator.step it := by
simp only [Iter.IsPlausibleStep, Monadic.isPlausibleStep_iff, step_eq_monadicStep]
constructor
· intro h
generalize hs : (step.mapIterator Iter.toIterM) = stepM at h
cases h
replace hs := congrArg (IterStep.mapIterator IterM.toIter) hs
simpa using hs
· rintro rfl
simp only [IterStep.mapIterator_mapIterator, Iter.toIterM_comp_toIter, IterStep.mapIterator_id]
theorem Iterator.step_eq_step [UpwardEnumerable α] [LE α] [DecidableLE α]
{it : Iter (α := Rxc.Iterator α) α} :
it.step = ⟨Iterator.step it, isPlausibleStep_iff.mpr rfl⟩ := by
simp [Iter.step, step_eq_monadicStep, Monadic.step_eq_step, IterM.Step.toPure]
instance Iterator.instIteratorCollect [UpwardEnumerable α] [LE α] [DecidableLE α]
{n : Type u → Type w} [Monad n] : IteratorCollect (Rxc.Iterator α) Id n :=
.defaultImplementation
instance Iterator.instIteratorCollectPartial [UpwardEnumerable α] [LE α] [DecidableLE α]
{n : Type u → Type w} [Monad n] : IteratorCollectPartial (Rxc.Iterator α) Id n :=
.defaultImplementation
theorem Iterator.Monadic.isPlausibleOutput_next {a}
[UpwardEnumerable α] [LE α] [DecidableLE α]
{it : IterM (α := Rxc.Iterator α) Id α} (h : it.internalState.next = some a)
(hP : a ≤ it.internalState.upperBound) :
it.IsPlausibleOutput a := by
simp [IterM.IsPlausibleOutput, Monadic.isPlausibleStep_iff, Monadic.step, h, hP]
theorem Iterator.Monadic.isPlausibleOutput_iff
[UpwardEnumerable α] [LE α] [DecidableLE α]
{it : IterM (α := Rxc.Iterator α) Id α} :
it.IsPlausibleOutput a ↔
it.internalState.next = some a ∧
a ≤ it.internalState.upperBound := by
simp [IterM.IsPlausibleOutput, isPlausibleStep_iff, Monadic.step]
split
· simp [*]
· constructor
· rintro ⟨it', hit'⟩
split at hit' <;> simp_all
· rename_i heq
rintro ⟨heq', h'⟩
simp only [heq', Option.some.injEq] at heq
simp_all
theorem Iterator.isPlausibleOutput_next
[UpwardEnumerable α] [LE α] [DecidableLE α]
{it : Iter (α := Rxc.Iterator α) α} (h : it.internalState.next = some a)
(hP : a ≤ it.internalState.upperBound) :
it.IsPlausibleOutput a := by
simp [Iter.IsPlausibleOutput, Monadic.isPlausibleOutput_iff, Iter.toIterM, h, hP]
theorem Iterator.isPlausibleOutput_iff
[UpwardEnumerable α] [LE α] [DecidableLE α]
{it : Iter (α := Rxc.Iterator α) α} :
it.IsPlausibleOutput a ↔
it.internalState.next = some a ∧
a ≤ it.internalState.upperBound := by
simp [Iter.IsPlausibleOutput, Monadic.isPlausibleOutput_iff, Iter.toIterM]
theorem Iterator.Monadic.isPlausibleSuccessorOf_iff
[UpwardEnumerable α] [LE α] [DecidableLE α]
{it' it : IterM (α := Rxc.Iterator α) Id α} :
it'.IsPlausibleSuccessorOf it ↔
∃ a, it.internalState.next = some a ∧
a ≤ it.internalState.upperBound ∧
UpwardEnumerable.succ? a = it'.internalState.next ∧
it'.internalState.upperBound = it.internalState.upperBound := by
simp only [IterM.IsPlausibleSuccessorOf]
constructor
· rintro ⟨step, h, h'⟩
cases h'
simp only [Monadic.step] at h
split at h
· cases h
· split at h
· simp only [IterStep.successor, Option.some.injEq] at h
cases h
exact ⟨_, _, _, rfl, rfl⟩
· cases h
· rintro ⟨a, h, hP, h'⟩
refine ⟨.yield it' a, rfl, ?_⟩
simp only [IterM.IsPlausibleStep, Iterator.IsPlausibleStep, step, h, hP, ↓reduceIte,
IterStep.yield.injEq, and_true]
simp [h'.1, ← h'.2]
theorem Iterator.isPlausibleSuccessorOf_iff
[UpwardEnumerable α] [LE α] [DecidableLE α]
{it' it : Iter (α := Rxc.Iterator α) α} :
it'.IsPlausibleSuccessorOf it ↔
∃ a, it.internalState.next = some a ∧
a ≤ it.internalState.upperBound ∧
UpwardEnumerable.succ? a = it'.internalState.next ∧
it'.internalState.upperBound = it.internalState.upperBound := by
simp [Iter.IsPlausibleSuccessorOf, Monadic.isPlausibleSuccessorOf_iff, Iter.toIterM]
theorem Iterator.isSome_next_of_isPlausibleIndirectOutput
[UpwardEnumerable α] [LE α] [DecidableLE α]
{it : Iter (α := Rxc.Iterator α) α} {out : α} (h : it.IsPlausibleIndirectOutput out) :
it.internalState.next.isSome := by
cases h
case direct h =>
rw [isPlausibleOutput_iff] at h
simp [h]
case indirect h _ =>
rw [isPlausibleSuccessorOf_iff] at h
obtain ⟨a, ha, _⟩ := h
simp [ha]
private def List.Sublist.filter_mono {l : List α} {P Q : α → Bool} (h : ∀ a, P a → Q a) :
List.Sublist (l.filter P) (l.filter Q) := by
apply List.Sublist.trans (l₂ := (l.filter Q).filter P)
· simp [Bool.and_eq_left_iff_imp.mpr (h _)]
· apply List.filter_sublist
private def List.length_filter_strict_mono {l : List α} {P Q : α → Bool} {a : α}
(h : ∀ a, P a → Q a) (ha : a ∈ l) (hPa : ¬ P a) (hQa : Q a) :
(l.filter P).length < (l.filter Q).length := by
have hsl : List.Sublist (l.filter P) (l.filter Q) := by
apply List.Sublist.filter_mono
exact h
apply Nat.lt_of_le_of_ne
· apply List.Sublist.length_le
exact hsl
· intro h
apply hPa
have heq := List.Sublist.eq_of_length hsl h
have : a ∈ List.filter Q l := List.mem_filter.mpr ⟨ha, hQa⟩
rw [← heq, List.mem_filter] at this
exact this.2
private def Iterator.instFinitenessRelation [UpwardEnumerable α] [LE α] [DecidableLE α]
[LawfulUpwardEnumerable α] [Rxc.IsAlwaysFinite α] :
FinitenessRelation (Rxc.Iterator α) Id where
rel it' it := it'.IsPlausibleSuccessorOf it
wf := by
constructor
intro it
have hnone : ∀ bound, Acc (fun it' it : IterM (α := Rxc.Iterator α) Id α => it'.IsPlausibleSuccessorOf it)
⟨⟨none, bound⟩⟩ := by
intro bound
constructor
intro it' ⟨step, hs₁, hs₂⟩
simp only [IterM.IsPlausibleStep, Iterator.IsPlausibleStep, Monadic.step] at hs₂
simp [hs₂, IterStep.successor] at hs₁
simp only [IterM.IsPlausibleSuccessorOf, IterM.IsPlausibleStep, Iterator.IsPlausibleStep,
Monadic.step, exists_eq_right] at hnone ⊢
match it with
| ⟨⟨none, _⟩⟩ => apply hnone
| ⟨⟨some init, bound⟩⟩ =>
obtain ⟨n, hn⟩ := Rxc.IsAlwaysFinite.finite init bound
induction n generalizing init with
| zero =>
simp only [succMany?_zero, Option.elim_some] at hn
constructor
simp [hn, IterStep.successor]
| succ n ih =>
constructor
rintro it'
simp only [succMany?_add_one_eq_succ?_bind_succMany?] at hn
match hs : succ? init with
| none =>
simp only [hs]
intro h
split at h
· cases h
apply hnone
· cases h
| some a =>
intro h
simp only [hs] at h hn
specialize ih _ hn
split at h
· cases h
exact ih
· cases h
subrelation := id
@[no_expose]
instance Iterator.instFinite [UpwardEnumerable α] [LE α] [DecidableLE α]
[LawfulUpwardEnumerable α] [Rxc.IsAlwaysFinite α] :
Finite (Rxc.Iterator α) Id :=
.of_finitenessRelation instFinitenessRelation
private def Iterator.instProductivenessRelation [UpwardEnumerable α] [LE α] [DecidableLE α]
[LawfulUpwardEnumerable α] :
ProductivenessRelation (Rxc.Iterator α) Id where
rel := emptyWf.rel
wf := emptyWf.wf
subrelation {it it'} h := by
exfalso
simp only [IterM.IsPlausibleSkipSuccessorOf, IterM.IsPlausibleStep,
Iterator.IsPlausibleStep, Monadic.step] at h
split at h
· cases h
· split at h
· cases h
· cases h
@[no_expose]
instance Iterator.instProductive [UpwardEnumerable α] [LE α] [DecidableLE α]
[LawfulUpwardEnumerable α] :
Productive (Rxc.Iterator α) Id :=
.of_productivenessRelation instProductivenessRelation
instance Iterator.instIteratorAccess [UpwardEnumerable α] [LE α] [DecidableLE α]
[LawfulUpwardEnumerable α] [LawfulUpwardEnumerableLE α] :
IteratorAccess (Rxc.Iterator α) Id where
nextAtIdx? it n := ⟨match it.internalState.next.bind (UpwardEnumerable.succMany? n) with
| none => .done
| some next => if next ≤ it.internalState.upperBound then
.yield ⟨⟨UpwardEnumerable.succ? next, it.internalState.upperBound⟩⟩ next
else
.done, (by
induction n generalizing it
· split <;> rename_i heq
· apply IterM.IsPlausibleNthOutputStep.done
simp only [Monadic.isPlausibleStep_iff, Monadic.step]
simp only [Option.bind_eq_none_iff, succMany?_zero, reduceCtorEq,
imp_false] at heq
cases heq' : it.internalState.next
· simp
· rw [heq'] at heq
exfalso
exact heq _ rfl
· cases heq' : it.internalState.next
· simp [heq'] at heq
simp only [heq', Option.bind_some, succMany?_zero, Option.some.injEq] at heq
cases heq
split <;> rename_i heq''
· apply IterM.IsPlausibleNthOutputStep.zero_yield
simp [Monadic.isPlausibleStep_iff, Monadic.step, heq', heq'']
· apply IterM.IsPlausibleNthOutputStep.done
simp [Monadic.isPlausibleStep_iff, Monadic.step, heq', heq'']
· rename_i n ih
split <;> rename_i heq
· cases heq' : it.internalState.next
· apply IterM.IsPlausibleNthOutputStep.done
simp only [Monadic.isPlausibleStep_iff, Monadic.step, heq']
· rename_i out
simp only [heq', Option.bind_some, succMany?_add_one_eq_succ?_bind_succMany?] at heq
specialize ih ⟨⟨UpwardEnumerable.succ? out, it.internalState.upperBound⟩⟩
simp only [heq] at ih
by_cases heq'' : out ≤ it.internalState.upperBound
· apply IterM.IsPlausibleNthOutputStep.yield
· simp only [Monadic.isPlausibleStep_iff, Monadic.step, heq', heq'', ↓reduceIte,
IterStep.yield.injEq]
exact ⟨rfl, rfl⟩
· exact ih
· apply IterM.IsPlausibleNthOutputStep.done
simp [Monadic.isPlausibleStep_iff, Monadic.step, heq', heq'']
· cases heq' : it.internalState.next
· simp [heq'] at heq
rename_i out
simp only [heq', Option.bind_some] at heq
have hle : UpwardEnumerable.LE out _ := ⟨n + 1, heq⟩
simp only [succMany?_add_one_eq_succ?_bind_succMany?] at heq
specialize ih ⟨⟨UpwardEnumerable.succ? out, it.internalState.upperBound⟩⟩
simp only [heq] at ih
by_cases hout : out ≤ it.internalState.upperBound
· apply IterM.IsPlausibleNthOutputStep.yield
· simp only [Monadic.isPlausibleStep_iff, Monadic.step, heq', hout, ↓reduceIte,
IterStep.yield.injEq]
exact ⟨rfl, rfl⟩
· apply ih
· rename_i next
haveI := UpwardEnumerable.instLETransOfLawfulUpwardEnumerableLE (α := α)
have := hout.imp (fun h : next ≤ it.internalState.upperBound => by
rw [← UpwardEnumerable.le_iff] at hle
exact Trans.trans hle h)
simp only [this, ↓reduceIte]
simp only [this, ↓reduceIte] at ih
apply IterM.IsPlausibleNthOutputStep.done
simp [Monadic.isPlausibleStep_iff, Monadic.step, heq', hout])⟩
instance Iterator.instLawfulDeterministicIterator [UpwardEnumerable α] [LE α] [DecidableLE α] :
LawfulDeterministicIterator (Rxc.Iterator α) Id where
isPlausibleStep_eq_eq it := ⟨Monadic.step it, rfl⟩
theorem Iterator.Monadic.isPlausibleIndirectOutput_iff
[UpwardEnumerable α] [LE α] [DecidableLE α] [LawfulUpwardEnumerableLE α]
[LawfulUpwardEnumerable α]
{it : IterM (α := Rxc.Iterator α) Id α} {out : α} :
it.IsPlausibleIndirectOutput out ↔
∃ n, it.internalState.next.bind (succMany? n ·) = some out ∧
out ≤ it.internalState.upperBound := by
constructor
· intro h
induction h
case direct h =>
rw [Monadic.isPlausibleOutput_iff] at h
refine ⟨0, by simp [h, LawfulUpwardEnumerable.succMany?_zero]⟩
case indirect h _ ih =>
rw [Monadic.isPlausibleSuccessorOf_iff] at h
obtain ⟨n, hn⟩ := ih
obtain ⟨a, ha, h₁, h₂, h₃⟩ := h
refine ⟨n + 1, ?_⟩
simp [ha, ← h₃, hn.2, succMany?_add_one_eq_succ?_bind_succMany?, h₂, hn]
· rintro ⟨n, hn, hu⟩
induction n generalizing it
case zero =>
apply IterM.IsPlausibleIndirectOutput.direct
rw [Monadic.isPlausibleOutput_iff]
exact ⟨by simpa [LawfulUpwardEnumerable.succMany?_zero] using hn, hu⟩
case succ ih =>
cases hn' : it.internalState.next
· simp [hn'] at hn
rename_i a
simp only [hn', Option.bind_some] at hn
have hle : UpwardEnumerable.LE a out := ⟨_, hn⟩
rw [succMany?_add_one_eq_succ?_bind_succMany?] at hn
cases hn' : succ? a
· simp only [hn', Option.bind_none, reduceCtorEq] at hn
rename_i a'
simp only [hn', Option.bind_some] at hn
specialize ih (it := ⟨some a', it.internalState.upperBound⟩) hn hu
refine IterM.IsPlausibleIndirectOutput.indirect ?_ ih
rw [Monadic.isPlausibleSuccessorOf_iff]
refine ⟨a, _, ?_, hn', rfl⟩
haveI := UpwardEnumerable.instLETransOfLawfulUpwardEnumerableLE (α := α)
exact Trans.trans (α := α) (r := (· ≤ ·)) (UpwardEnumerable.le_iff.mpr hle) hu
theorem Iterator.isPlausibleIndirectOutput_iff
[UpwardEnumerable α] [LE α] [DecidableLE α]
[LawfulUpwardEnumerable α] [LawfulUpwardEnumerableLE α]
{it : Iter (α := Rxc.Iterator α) α} {out : α} :
it.IsPlausibleIndirectOutput out ↔
∃ n, it.internalState.next.bind (succMany? n ·) = some out ∧
out ≤ it.internalState.upperBound := by
simp only [Iter.isPlausibleIndirectOutput_iff_isPlausibleIndirectOutput_toIterM,
Monadic.isPlausibleIndirectOutput_iff, Iter.toIterM]
section IteratorLoop
/--
An efficient {name}`IteratorLoop` instance:
As long as the compiler cannot optimize away the {name}`Option` in the internal state, we use a special
loop implementation.
-/
@[always_inline, inline]
instance Iterator.instIteratorLoop [UpwardEnumerable α] [LE α] [DecidableLE α]
[LawfulUpwardEnumerable α] [LawfulUpwardEnumerableLE α]
{n : Type u → Type w} [Monad n] :
IteratorLoop (Rxc.Iterator α) Id n where
forIn _ γ Pl wf it init f :=
match it with
| ⟨⟨some next, upperBound⟩⟩ =>
if hu : next ≤ upperBound then
loop γ Pl wf upperBound next init (fun a ha₁ ha₂ c => f a ?hf c) next ?hle hu
else
return init
| ⟨⟨none, _⟩⟩ => return init
where
@[specialize]
loop γ Pl wf (upperBound : α) least acc
(f : (out : α) → UpwardEnumerable.LE least out → out ≤ upperBound → (c : γ) → n (Subtype (fun s : ForInStep γ => Pl out c s)))
(next : α) (hl : UpwardEnumerable.LE least next) (hu : next ≤ upperBound) : n γ := do
match ← f next hl hu acc with
| ⟨.yield acc', _⟩ =>
match hs : UpwardEnumerable.succ? next with
| some next' =>
if hu : next' ≤ upperBound then
loop γ Pl wf upperBound least acc' f next' ?hle' hu
else
return acc'
| none => return acc'
| ⟨.done acc', _⟩ => return acc'
termination_by IteratorLoop.WithWF.mk ⟨⟨some next, upperBound⟩⟩ acc (hwf := wf)
decreasing_by
simp [IteratorLoop.rel, Monadic.isPlausibleStep_iff,
Monadic.step, *]
finally
case hf =>
rw [Monadic.isPlausibleIndirectOutput_iff]
obtain ⟨n, hn⟩ := ha₁
exact ⟨n, hn, ha₂⟩
case hle =>
exact UpwardEnumerable.le_refl _
case hle' =>
refine UpwardEnumerable.le_trans hl ⟨1, ?_⟩
simp [succMany?_one, hs]
/--
An efficient {name}`IteratorLoop` instance:
As long as the compiler cannot optimize away the {name}`Option` in the internal state, we use a special
loop implementation.
-/
partial instance Iterator.instIteratorLoopPartial [UpwardEnumerable α] [LE α] [DecidableLE α]
[LawfulUpwardEnumerable α] [LawfulUpwardEnumerableLE α]
{n : Type u → Type w} [Monad n] : IteratorLoopPartial (Rxc.Iterator α) Id n where
forInPartial _ γ it init f :=
match it with
| ⟨⟨some next, upperBound⟩⟩ =>
if hu : next ≤ upperBound then
loop γ upperBound next init (fun a ha₁ ha₂ c => f a ?hf c) next ?hle hu
else
return init
| ⟨⟨none, _⟩⟩ => return init
where
@[specialize]
loop γ (upperBound : α) least acc
(f : (out : α) → UpwardEnumerable.LE least out → out ≤ upperBound → (c : γ) → n (ForInStep γ))
(next : α) (hl : UpwardEnumerable.LE least next) (hu : next ≤ upperBound) : n γ := do
match ← f next hl hu acc with
| .yield acc' =>
match hs : succ? next with
| some next' =>
if hu : next' ≤ upperBound then
loop γ upperBound least acc' f next' ?hle' hu
else
return acc'
| none => return acc'
| .done acc' => return acc'
finally
case hf =>
rw [Monadic.isPlausibleIndirectOutput_iff]
obtain ⟨n, hn⟩ := ha₁
exact ⟨n, hn, ha₂⟩
case hle =>
exact UpwardEnumerable.le_refl _
case hle' =>
refine UpwardEnumerable.le_trans hl ⟨1, ?_⟩
simp [succMany?_one, hs]
theorem Iterator.instIteratorLoop.loop_eq [UpwardEnumerable α] [LE α] [DecidableLE α]
[LawfulUpwardEnumerable α] [LawfulUpwardEnumerableLE α]
{n : Type u → Type w} [Monad n] [LawfulMonad n] {γ : Type u}
{lift} [Internal.LawfulMonadLiftBindFunction lift]
{PlausibleForInStep} {upperBound} {next} {hl} {hu} {f} {acc} {wf} :
loop (α := α) (n := n) γ PlausibleForInStep wf upperBound least acc f next hl hu =
(do
match ← f next hl hu acc with
| ⟨.yield c, _⟩ =>
letI it' : IterM (α := Rxc.Iterator α) Id α := ⟨⟨succ? next, upperBound⟩⟩
IterM.DefaultConsumers.forIn' (m := Id) lift γ
PlausibleForInStep wf it' c it'.IsPlausibleIndirectOutput (fun _ => id)
(fun b h c => f b
(by
refine UpwardEnumerable.le_trans hl ?_
simp only [Monadic.isPlausibleIndirectOutput_iff, it',
← succMany?_add_one_eq_succ?_bind_succMany?] at h
exact ⟨h.choose + 1, h.choose_spec.1⟩)
(by
simp only [Monadic.isPlausibleIndirectOutput_iff, it'] at h
exact h.choose_spec.2) c)
| ⟨.done c, _⟩ => return c) := by
rw [loop]
apply bind_congr
intro step
split
· split
· split
· simp only [*]
rw [IterM.DefaultConsumers.forIn']
simp only [Monadic.step_eq_step, Monadic.step, ↓reduceIte, *,
Internal.LawfulMonadLiftBindFunction.liftBind_pure]
rw [loop_eq (lift := lift), Shrink.inflate_deflate]
apply bind_congr
intro step
split
· apply IterM.DefaultConsumers.forIn'_eq_forIn'
intros; rfl
· simp
· simp only [*]
rw [IterM.DefaultConsumers.forIn']
simp [Monadic.step_eq_step, Monadic.step, *,
Internal.LawfulMonadLiftBindFunction.liftBind_pure]
· simp only [*]
rw [IterM.DefaultConsumers.forIn']
simp [Monadic.step_eq_step, Monadic.step, Internal.LawfulMonadLiftBindFunction.liftBind_pure]
· simp
termination_by IteratorLoop.WithWF.mk ⟨⟨some next, upperBound⟩⟩ acc (hwf := wf)
decreasing_by
simp [IteratorLoop.rel, Monadic.isPlausibleStep_iff, Monadic.step, *]
instance Iterator.instLawfulIteratorLoop [UpwardEnumerable α] [LE α] [DecidableLE α]
[LawfulUpwardEnumerable α] [LawfulUpwardEnumerableLE α]
{n : Type u → Type w} [Monad n] [LawfulMonad n] :
LawfulIteratorLoop (Rxc.Iterator α) Id n where
lawful := by
intro lift instLawfulMonadLiftFunction
ext γ PlausibleForInStep hwf it init f
simp only [IteratorLoop.forIn, IteratorLoop.defaultImplementation]
rw [IterM.DefaultConsumers.forIn']
simp only [Monadic.step_eq_step, Monadic.step]
simp only [Internal.LawfulMonadLiftBindFunction.liftBind_pure]
split
· rename_i it f next upperBound f'
simp
split
· simp only
rw [instIteratorLoop.loop_eq (lift := lift)]
apply bind_congr
intro step
split
· apply IterM.DefaultConsumers.forIn'_eq_forIn'
intro b c hPb hQb
congr
· simp
· simp
· simp
end IteratorLoop
end Rxc
namespace Rxo
variable {α : Type u} {lo hi a : α}
/-- Internal state of the range iterators. Do not depend on its internals. -/
@[unbox]
protected structure Iterator (α : Type u) where
next : Option α
upperBound : α
/--
The pure function mapping a range iterator of type {name}`IterM` to the next step of the iterator.
This function is prefixed with {lit}`Monadic` in order to disambiguate it from the version for iterators
of type {name}`Iter`.
-/
@[inline]
def Iterator.Monadic.step [UpwardEnumerable α] [LT α] [DecidableLT α]
(it : IterM (α := Rxo.Iterator α) Id α) :
IterStep (IterM (α := Rxo.Iterator α) Id α) α :=
match it.internalState.next with
| none => .done
| some next =>
if next < it.internalState.upperBound then
.yield ⟨⟨UpwardEnumerable.succ? next, it.internalState.upperBound⟩⟩ next
else
.done
/--
The pure function mapping a range iterator of type {name}`Iter` to the next step of the iterator.
-/
@[always_inline, inline]
def Iterator.step [UpwardEnumerable α] [LT α] [DecidableLT α]
(it : Iter (α := Rxo.Iterator α) α) :
IterStep (Iter (α := Rxo.Iterator α) α) α :=
match it.internalState.next with
| none => .done
| some next => if next < it.internalState.upperBound then
.yield ⟨⟨UpwardEnumerable.succ? next, it.internalState.upperBound⟩⟩ next
else
.done
theorem Iterator.step_eq_monadicStep [UpwardEnumerable α] [LT α] [DecidableLT α]
{it : Iter (α := Rxo.Iterator α) α} :
Iterator.step it = (Iterator.Monadic.step it.toIterM).mapIterator IterM.toIter := by
simp only [step, Monadic.step, Iter.toIterM]
split
· rfl
· split <;> rfl
@[always_inline, inline]
instance [UpwardEnumerable α] [LT α] [DecidableLT α] :
Iterator (Rxo.Iterator α) Id α where
IsPlausibleStep it step := step = Iterator.Monadic.step it
step it := pure (.deflate ⟨Iterator.Monadic.step it, rfl⟩)
theorem Iterator.Monadic.isPlausibleStep_iff [UpwardEnumerable α] [LT α] [DecidableLT α]
{it : IterM (α := Rxo.Iterator α) Id α} {step} :
it.IsPlausibleStep step ↔ step = Iterator.Monadic.step it := by
exact Iff.rfl
theorem Iterator.Monadic.step_eq_step [UpwardEnumerable α] [LT α] [DecidableLT α]
{it : IterM (α := Rxo.Iterator α) Id α} :
it.step = pure (.deflate ⟨Iterator.Monadic.step it, isPlausibleStep_iff.mpr rfl⟩) := by
simp [IterM.step, Iterators.Iterator.step]
theorem Iterator.isPlausibleStep_iff [UpwardEnumerable α] [LT α] [DecidableLT α]
{it : Iter (α := Rxo.Iterator α) α} {step} :
it.IsPlausibleStep step ↔ step = Iterator.step it := by
simp only [Iter.IsPlausibleStep, Monadic.isPlausibleStep_iff, step_eq_monadicStep]
constructor
· intro h
generalize hs : (step.mapIterator Iter.toIterM) = stepM at h
cases h
replace hs := congrArg (IterStep.mapIterator IterM.toIter) hs
simpa using hs
· rintro rfl
simp only [IterStep.mapIterator_mapIterator, Iter.toIterM_comp_toIter, IterStep.mapIterator_id]
theorem Iterator.step_eq_step [UpwardEnumerable α] [LT α] [DecidableLT α]
{it : Iter (α := Rxo.Iterator α) α} :
it.step = ⟨Iterator.step it, isPlausibleStep_iff.mpr rfl⟩ := by
simp [Iter.step, step_eq_monadicStep, Monadic.step_eq_step, IterM.Step.toPure]
instance Iterator.instIteratorCollect [UpwardEnumerable α] [LT α] [DecidableLT α]
{n : Type u → Type w} [Monad n] : IteratorCollect (Rxo.Iterator α) Id n :=
.defaultImplementation
instance Iterator.instIteratorCollectPartial [UpwardEnumerable α] [LT α] [DecidableLT α]
{n : Type u → Type w} [Monad n] : IteratorCollectPartial (Rxo.Iterator α) Id n :=
.defaultImplementation
theorem Iterator.Monadic.isPlausibleOutput_next {a}
[UpwardEnumerable α] [LT α] [DecidableLT α]
{it : IterM (α := Rxo.Iterator α) Id α} (h : it.internalState.next = some a)
(hP : a < it.internalState.upperBound) :
it.IsPlausibleOutput a := by
simp [IterM.IsPlausibleOutput, Monadic.isPlausibleStep_iff, Monadic.step, h, hP]
theorem Iterator.Monadic.isPlausibleOutput_iff
[UpwardEnumerable α] [LT α] [DecidableLT α]
{it : IterM (α := Rxo.Iterator α) Id α} :
it.IsPlausibleOutput a ↔
it.internalState.next = some a ∧
a < it.internalState.upperBound := by
simp [IterM.IsPlausibleOutput, isPlausibleStep_iff, Monadic.step]
split
· simp [*]
· constructor
· rintro ⟨it', hit'⟩
split at hit' <;> simp_all
· rename_i heq
rintro ⟨heq', h'⟩
simp only [heq', Option.some.injEq] at heq
simp_all
theorem Iterator.isPlausibleOutput_next
[UpwardEnumerable α] [LT α] [DecidableLT α]
{it : Iter (α := Rxo.Iterator α) α} (h : it.internalState.next = some a)
(hP : a < it.internalState.upperBound) :
it.IsPlausibleOutput a := by
simp [Iter.IsPlausibleOutput, Monadic.isPlausibleOutput_iff, Iter.toIterM, h, hP]
theorem Iterator.isPlausibleOutput_iff
[UpwardEnumerable α] [LT α] [DecidableLT α]
{it : Iter (α := Rxo.Iterator α) α} :
it.IsPlausibleOutput a ↔
it.internalState.next = some a ∧
a < it.internalState.upperBound := by
simp [Iter.IsPlausibleOutput, Monadic.isPlausibleOutput_iff, Iter.toIterM]
theorem Iterator.Monadic.isPlausibleSuccessorOf_iff
[UpwardEnumerable α] [LT α] [DecidableLT α]
{it' it : IterM (α := Rxo.Iterator α) Id α} :
it'.IsPlausibleSuccessorOf it ↔
∃ a, it.internalState.next = some a ∧
a < it.internalState.upperBound ∧
UpwardEnumerable.succ? a = it'.internalState.next ∧
it'.internalState.upperBound = it.internalState.upperBound := by
simp only [IterM.IsPlausibleSuccessorOf]
constructor
· rintro ⟨step, h, h'⟩
cases h'
simp only [Monadic.step] at h
split at h
· cases h
· split at h
· simp only [IterStep.successor, Option.some.injEq] at h
cases h
exact ⟨_, _, _, rfl, rfl⟩
· cases h
· rintro ⟨a, h, hP, h'⟩
refine ⟨.yield it' a, rfl, ?_⟩
simp only [IterM.IsPlausibleStep, Iterator.IsPlausibleStep, step, h, hP, ↓reduceIte,
IterStep.yield.injEq, and_true]
simp [h'.1, ← h'.2]
theorem Iterator.isPlausibleSuccessorOf_iff
[UpwardEnumerable α] [LT α] [DecidableLT α]
{it' it : Iter (α := Rxo.Iterator α) α} :
it'.IsPlausibleSuccessorOf it ↔
∃ a, it.internalState.next = some a ∧
a < it.internalState.upperBound ∧
UpwardEnumerable.succ? a = it'.internalState.next ∧
it'.internalState.upperBound = it.internalState.upperBound := by
simp [Iter.IsPlausibleSuccessorOf, Monadic.isPlausibleSuccessorOf_iff, Iter.toIterM]
theorem Iterator.isSome_next_of_isPlausibleIndirectOutput
[UpwardEnumerable α] [LT α] [DecidableLT α]
{it : Iter (α := Rxo.Iterator α) α} {out : α} (h : it.IsPlausibleIndirectOutput out) :
it.internalState.next.isSome := by
cases h
case direct h =>
rw [isPlausibleOutput_iff] at h
simp [h]
case indirect h _ =>
rw [isPlausibleSuccessorOf_iff] at h
obtain ⟨a, ha, _⟩ := h
simp [ha]
private def List.Sublist.filter_mono {l : List α} {P Q : α → Bool} (h : ∀ a, P a → Q a) :
List.Sublist (l.filter P) (l.filter Q) := by
apply List.Sublist.trans (l₂ := (l.filter Q).filter P)
· simp [Bool.and_eq_left_iff_imp.mpr (h _)]
· apply List.filter_sublist
private def List.length_filter_strict_mono {l : List α} {P Q : α → Bool} {a : α}
(h : ∀ a, P a → Q a) (ha : a ∈ l) (hPa : ¬ P a) (hQa : Q a) :
(l.filter P).length < (l.filter Q).length := by
have hsl : List.Sublist (l.filter P) (l.filter Q) := by
apply List.Sublist.filter_mono
exact h
apply Nat.lt_of_le_of_ne
· apply List.Sublist.length_le
exact hsl
· intro h
apply hPa
have heq := List.Sublist.eq_of_length hsl h
have : a ∈ List.filter Q l := List.mem_filter.mpr ⟨ha, hQa⟩
rw [← heq, List.mem_filter] at this
exact this.2
private def Iterator.instFinitenessRelation [UpwardEnumerable α] [LT α] [DecidableLT α]
[LawfulUpwardEnumerable α] [Rxo.IsAlwaysFinite α] :
FinitenessRelation (Rxo.Iterator α) Id where
rel it' it := it'.IsPlausibleSuccessorOf it
wf := by
constructor
intro it
have hnone : ∀ bound, Acc (fun it' it : IterM (α := Rxo.Iterator α) Id α => it'.IsPlausibleSuccessorOf it)
⟨⟨none, bound⟩⟩ := by
intro bound
constructor
intro it' ⟨step, hs₁, hs₂⟩
simp only [IterM.IsPlausibleStep, Iterator.IsPlausibleStep, Monadic.step] at hs₂
simp [hs₂, IterStep.successor] at hs₁
simp only [IterM.IsPlausibleSuccessorOf, IterM.IsPlausibleStep, Iterator.IsPlausibleStep,
Monadic.step, exists_eq_right] at hnone ⊢
match it with
| ⟨⟨none, _⟩⟩ => apply hnone
| ⟨⟨some init, bound⟩⟩ =>
obtain ⟨n, hn⟩ := Rxo.IsAlwaysFinite.finite init bound
induction n generalizing init with
| zero =>
simp only [succMany?_zero, Option.elim_some] at hn
constructor
simp [hn, IterStep.successor]
| succ n ih =>
constructor
rintro it'
simp only [succMany?_add_one_eq_succ?_bind_succMany?] at hn
match hs : succ? init with
| none =>
simp only [hs]
intro h
split at h
· cases h
apply hnone
· cases h
| some a =>
intro h
simp only [hs] at h hn
specialize ih _ hn
split at h
· cases h
exact ih
· cases h
subrelation := id
@[no_expose]
instance Iterator.instFinite [UpwardEnumerable α] [LT α] [DecidableLT α]
[LawfulUpwardEnumerable α] [Rxo.IsAlwaysFinite α] :
Finite (Rxo.Iterator α) Id :=
.of_finitenessRelation instFinitenessRelation
private def Iterator.instProductivenessRelation [UpwardEnumerable α] [LT α] [DecidableLT α]
[LawfulUpwardEnumerable α] :
ProductivenessRelation (Rxo.Iterator α) Id where
rel := emptyWf.rel
wf := emptyWf.wf
subrelation {it it'} h := by
exfalso
simp only [IterM.IsPlausibleSkipSuccessorOf, IterM.IsPlausibleStep,
Iterator.IsPlausibleStep, Monadic.step] at h
split at h
· cases h
· split at h
· cases h
· cases h
@[no_expose]
instance Iterator.instProductive [UpwardEnumerable α] [LT α] [DecidableLT α]
[LawfulUpwardEnumerable α] :
Productive (Rxo.Iterator α) Id :=
.of_productivenessRelation instProductivenessRelation
instance Iterator.instIteratorAccess [UpwardEnumerable α] [LT α] [DecidableLT α]
[LawfulUpwardEnumerable α] [LawfulUpwardEnumerableLT α] :
IteratorAccess (Rxo.Iterator α) Id where
nextAtIdx? it n := ⟨match it.internalState.next.bind (UpwardEnumerable.succMany? n) with
| none => .done
| some next => if next < it.internalState.upperBound then
.yield ⟨⟨UpwardEnumerable.succ? next, it.internalState.upperBound⟩⟩ next
else
.done, (by
induction n generalizing it
· split <;> rename_i heq
· apply IterM.IsPlausibleNthOutputStep.done
simp only [Monadic.isPlausibleStep_iff, Monadic.step]
simp only [Option.bind_eq_none_iff, succMany?_zero, reduceCtorEq,
imp_false] at heq
cases heq' : it.internalState.next
· simp
· rw [heq'] at heq
exfalso
exact heq _ rfl
· cases heq' : it.internalState.next
· simp [heq'] at heq
simp only [heq', Option.bind_some, succMany?_zero, Option.some.injEq] at heq
cases heq
split <;> rename_i heq''
· apply IterM.IsPlausibleNthOutputStep.zero_yield
simp [Monadic.isPlausibleStep_iff, Monadic.step, heq', heq'']
· apply IterM.IsPlausibleNthOutputStep.done
simp [Monadic.isPlausibleStep_iff, Monadic.step, heq', heq'']
· rename_i n ih
split <;> rename_i heq
· cases heq' : it.internalState.next
· apply IterM.IsPlausibleNthOutputStep.done
simp only [Monadic.isPlausibleStep_iff, Monadic.step, heq']
· rename_i out
simp only [heq', Option.bind_some, succMany?_add_one_eq_succ?_bind_succMany?] at heq
specialize ih ⟨⟨UpwardEnumerable.succ? out, it.internalState.upperBound⟩⟩
simp only [heq] at ih
by_cases heq'' : out < it.internalState.upperBound
· apply IterM.IsPlausibleNthOutputStep.yield
· simp only [Monadic.isPlausibleStep_iff, Monadic.step, heq', heq'', ↓reduceIte,
IterStep.yield.injEq]
exact ⟨rfl, rfl⟩
· exact ih
· apply IterM.IsPlausibleNthOutputStep.done
simp [Monadic.isPlausibleStep_iff, Monadic.step, heq', heq'']
· cases heq' : it.internalState.next
· simp [heq'] at heq
rename_i out
simp only [heq', Option.bind_some] at heq
have hlt : UpwardEnumerable.LT out _ := ⟨n, heq⟩
simp only [succMany?_add_one_eq_succ?_bind_succMany?] at heq
specialize ih ⟨⟨UpwardEnumerable.succ? out, it.internalState.upperBound⟩⟩
simp only [heq] at ih
by_cases hout : out < it.internalState.upperBound
· apply IterM.IsPlausibleNthOutputStep.yield
· simp only [Monadic.isPlausibleStep_iff, Monadic.step, heq', hout, ↓reduceIte,
IterStep.yield.injEq]
exact ⟨rfl, rfl⟩
· apply ih
· rename_i next
haveI := UpwardEnumerable.instLTTransOfLawfulUpwardEnumerableLT (α := α)
have := hout.imp (fun h : next < it.internalState.upperBound => by
rw [← UpwardEnumerable.lt_iff] at hlt
exact Trans.trans hlt h)
simp only [this, ↓reduceIte]
simp only [this, ↓reduceIte] at ih
apply IterM.IsPlausibleNthOutputStep.done
simp [Monadic.isPlausibleStep_iff, Monadic.step, heq', hout])⟩
instance Iterator.instLawfulDeterministicIterator [UpwardEnumerable α] [LT α] [DecidableLT α] :
LawfulDeterministicIterator (Rxo.Iterator α) Id where
isPlausibleStep_eq_eq it := ⟨Monadic.step it, rfl⟩
theorem Iterator.Monadic.isPlausibleIndirectOutput_iff
[UpwardEnumerable α] [LT α] [DecidableLT α] [LawfulUpwardEnumerableLT α]
[LawfulUpwardEnumerable α]
{it : IterM (α := Rxo.Iterator α) Id α} {out : α} :
it.IsPlausibleIndirectOutput out ↔
∃ n, it.internalState.next.bind (succMany? n ·) = some out ∧
out < it.internalState.upperBound := by
constructor
· intro h
induction h
case direct h =>
rw [Monadic.isPlausibleOutput_iff] at h
refine ⟨0, by simp [h, LawfulUpwardEnumerable.succMany?_zero]⟩
case indirect h _ ih =>
rw [Monadic.isPlausibleSuccessorOf_iff] at h
obtain ⟨n, hn⟩ := ih
obtain ⟨a, ha, h₁, h₂, h₃⟩ := h
refine ⟨n + 1, ?_⟩
simp [ha, ← h₃, hn.2, succMany?_add_one_eq_succ?_bind_succMany?, h₂, hn]
· rintro ⟨n, hn, hu⟩
induction n generalizing it
case zero =>
apply IterM.IsPlausibleIndirectOutput.direct
rw [Monadic.isPlausibleOutput_iff]
exact ⟨by simpa [LawfulUpwardEnumerable.succMany?_zero] using hn, hu⟩
case succ ih =>
cases hn' : it.internalState.next
· simp [hn'] at hn
rename_i a
simp only [hn', Option.bind_some] at hn
have hlt : UpwardEnumerable.LT a out := ⟨_, hn⟩
rw [succMany?_add_one_eq_succ?_bind_succMany?] at hn
cases hn' : succ? a
· simp only [hn', Option.bind_none, reduceCtorEq] at hn
rename_i a'
simp only [hn', Option.bind_some] at hn
specialize ih (it := ⟨some a', it.internalState.upperBound⟩) hn hu
refine IterM.IsPlausibleIndirectOutput.indirect ?_ ih
rw [Monadic.isPlausibleSuccessorOf_iff]
refine ⟨a, _, ?_, hn', rfl⟩
haveI := UpwardEnumerable.instLTTransOfLawfulUpwardEnumerableLT (α := α)
exact Trans.trans (α := α) (UpwardEnumerable.lt_iff.mpr hlt) hu
theorem Iterator.isPlausibleIndirectOutput_iff
[UpwardEnumerable α] [LT α] [DecidableLT α]
[LawfulUpwardEnumerable α] [LawfulUpwardEnumerableLT α]
{it : Iter (α := Rxo.Iterator α) α} {out : α} :
it.IsPlausibleIndirectOutput out ↔
∃ n, it.internalState.next.bind (succMany? n ·) = some out ∧
out < it.internalState.upperBound := by
simp only [Iter.isPlausibleIndirectOutput_iff_isPlausibleIndirectOutput_toIterM,
Monadic.isPlausibleIndirectOutput_iff, Iter.toIterM]
section IteratorLoop
/--
An efficient {name}`IteratorLoop` instance:
As long as the compiler cannot optimize away the {name}`Option` in the internal state, we use a special
loop implementation.
-/
@[always_inline, inline]
instance Iterator.instIteratorLoop [UpwardEnumerable α] [LT α] [DecidableLT α]
[LawfulUpwardEnumerable α] [LawfulUpwardEnumerableLT α]
{n : Type u → Type w} [Monad n] :
IteratorLoop (Rxo.Iterator α) Id n where
forIn _ γ Pl wf it init f :=
match it with
| ⟨⟨some next, upperBound⟩⟩ =>
if hu : next < upperBound then
loop γ Pl wf upperBound next init (fun a ha₁ ha₂ c => f a ?hf c) next ?hle hu
else
return init
| ⟨⟨none, _⟩⟩ => return init
where
@[specialize]
loop γ Pl wf (upperBound : α) least acc
(f : (out : α) → UpwardEnumerable.LE least out → out < upperBound → (c : γ) → n (Subtype (fun s : ForInStep γ => Pl out c s)))
(next : α) (hl : UpwardEnumerable.LE least next) (hu : next < upperBound) : n γ := do
match ← f next hl hu acc with
| ⟨.yield acc', _⟩ =>
match hs : UpwardEnumerable.succ? next with
| some next' =>
if hu : next' < upperBound then
loop γ Pl wf upperBound least acc' f next' ?hle' hu
else
return acc'
| none => return acc'
| ⟨.done acc', _⟩ => return acc'
termination_by IteratorLoop.WithWF.mk ⟨⟨some next, upperBound⟩⟩ acc (hwf := wf)
decreasing_by
simp [IteratorLoop.rel, Monadic.isPlausibleStep_iff,
Monadic.step, *]
finally
case hf =>
rw [Monadic.isPlausibleIndirectOutput_iff]
obtain ⟨n, hn⟩ := ha₁
exact ⟨n, hn, ha₂⟩
case hle =>
exact UpwardEnumerable.le_refl _
case hle' =>
refine UpwardEnumerable.le_trans hl ⟨1, ?_⟩
simp [succMany?_one, hs]
/--
An efficient {name}`IteratorLoopPartial` instance:
As long as the compiler cannot optimize away the {name}`Option` in the internal state, we use a special
loop implementation.
-/
partial instance Iterator.instIteratorLoopPartial [UpwardEnumerable α] [LT α] [DecidableLT α]
[LawfulUpwardEnumerable α] [LawfulUpwardEnumerableLT α]
{n : Type u → Type w} [Monad n] : IteratorLoopPartial (Rxo.Iterator α) Id n where
forInPartial _ γ it init f :=
match it with
| ⟨⟨some next, upperBound⟩⟩ =>
if hu : next < upperBound then
loop γ upperBound next init (fun a ha₁ ha₂ c => f a ?hf c) next ?hle hu
else
return init
| ⟨⟨none, _⟩⟩ => return init
where
@[specialize]
loop γ (upperBound : α) least acc
(f : (out : α) → UpwardEnumerable.LE least out → out < upperBound → (c : γ) → n (ForInStep γ))
(next : α) (hl : UpwardEnumerable.LE least next) (hu : next < upperBound) : n γ := do
match ← f next hl hu acc with
| .yield acc' =>
match hs : succ? next with
| some next' =>
if hu : next' < upperBound then
loop γ upperBound least acc' f next' ?hle' hu
else
return acc'
| none => return acc'
| .done acc' => return acc'
finally
case hf =>
rw [Monadic.isPlausibleIndirectOutput_iff]
obtain ⟨n, hn⟩ := ha₁
exact ⟨n, hn, ha₂⟩
case hle =>
exact UpwardEnumerable.le_refl _
case hle' =>
refine UpwardEnumerable.le_trans hl ⟨1, ?_⟩
simp [succMany?_one, hs]
theorem Iterator.instIteratorLoop.loop_eq [UpwardEnumerable α] [LT α] [DecidableLT α]
[LawfulUpwardEnumerable α] [LawfulUpwardEnumerableLT α]
{n : Type u → Type w} [Monad n] [LawfulMonad n] {γ : Type u}
{lift} [Internal.LawfulMonadLiftBindFunction lift]
{PlausibleForInStep} {upperBound} {next} {hl} {hu} {f} {acc} {wf} :
loop (α := α) (n := n) γ PlausibleForInStep wf upperBound least acc f next hl hu =
(do
match ← f next hl hu acc with
| ⟨.yield c, _⟩ =>
letI it' : IterM (α := Rxo.Iterator α) Id α := ⟨⟨succ? next, upperBound⟩⟩
IterM.DefaultConsumers.forIn' (m := Id) lift γ
PlausibleForInStep wf it' c it'.IsPlausibleIndirectOutput (fun _ => id)
(fun b h c => f b
(by
refine UpwardEnumerable.le_trans hl ?_
simp only [Monadic.isPlausibleIndirectOutput_iff, it',
← succMany?_add_one_eq_succ?_bind_succMany?] at h
exact ⟨h.choose + 1, h.choose_spec.1⟩)
(by
simp only [Monadic.isPlausibleIndirectOutput_iff, it'] at h
exact h.choose_spec.2) c)
| ⟨.done c, _⟩ => return c) := by
rw [loop]
apply bind_congr
intro step
split
· split
· split
· simp only [*]
rw [IterM.DefaultConsumers.forIn']
simp only [Monadic.step_eq_step, Monadic.step, ↓reduceIte, *,
Internal.LawfulMonadLiftBindFunction.liftBind_pure]
rw [loop_eq (lift := lift), Shrink.inflate_deflate]
apply bind_congr
intro step
split
· apply IterM.DefaultConsumers.forIn'_eq_forIn'
intros; rfl
· simp
· simp only [*]
rw [IterM.DefaultConsumers.forIn']
simp [Monadic.step_eq_step, Monadic.step, *,
Internal.LawfulMonadLiftBindFunction.liftBind_pure]
· simp only [*]
rw [IterM.DefaultConsumers.forIn']
simp [Monadic.step_eq_step, Monadic.step, Internal.LawfulMonadLiftBindFunction.liftBind_pure]
· simp
termination_by IteratorLoop.WithWF.mk ⟨⟨some next, upperBound⟩⟩ acc (hwf := wf)
decreasing_by
simp [IteratorLoop.rel, Monadic.isPlausibleStep_iff, Monadic.step, *]
instance Iterator.instLawfulIteratorLoop [UpwardEnumerable α] [LT α] [DecidableLT α]
[LawfulUpwardEnumerable α] [LawfulUpwardEnumerableLT α]
{n : Type u → Type w} [Monad n] [LawfulMonad n] :
LawfulIteratorLoop (Rxo.Iterator α) Id n where
lawful := by
intro lift instLawfulMonadLiftFunction
ext γ PlausibleForInStep hwf it init f
simp only [IteratorLoop.forIn, IteratorLoop.defaultImplementation]
rw [IterM.DefaultConsumers.forIn']
simp only [Monadic.step_eq_step, Monadic.step]
simp only [Internal.LawfulMonadLiftBindFunction.liftBind_pure]
split
· rename_i it f next upperBound f'
simp
split
· simp only
rw [instIteratorLoop.loop_eq (lift := lift)]
apply bind_congr
intro step
split
· apply IterM.DefaultConsumers.forIn'_eq_forIn'
intro b c hPb hQb
congr
· simp
· simp
· simp
end IteratorLoop
end Rxo
namespace Rxi
variable {α : Type u} {lo a : α}
/-- Internal state of the range iterators. Do not depend on its internals. -/
@[unbox]
protected structure Iterator (α : Type u) where
next : Option α
/--
The pure function mapping a range iterator of type {name}`IterM` to the next step of the iterator.
This function is prefixed with {lit}`Monadic` in order to disambiguate it from the version for iterators
of type {name}`Iter`.
-/
@[inline]
def Iterator.Monadic.step [UpwardEnumerable α]
(it : IterM (α := Rxi.Iterator α) Id α) :
IterStep (IterM (α := Rxi.Iterator α) Id α) α :=
match it.internalState.next with
| none => .done
| some next => .yield ⟨⟨UpwardEnumerable.succ? next⟩⟩ next
/--
The pure function mapping a range iterator of type {name}`Iter` to the next step of the iterator.
-/
@[always_inline, inline]
def Iterator.step [UpwardEnumerable α]
(it : Iter (α := Rxi.Iterator α) α) :
IterStep (Iter (α := Rxi.Iterator α) α) α :=
match it.internalState.next with
| none => .done
| some next => .yield ⟨⟨UpwardEnumerable.succ? next⟩⟩ next
theorem Iterator.step_eq_monadicStep [UpwardEnumerable α]
{it : Iter (α := Rxi.Iterator α) α} :
Iterator.step it = (Iterator.Monadic.step it.toIterM).mapIterator IterM.toIter := by
simp only [step, Monadic.step, Iter.toIterM]
split <;> rfl
@[always_inline, inline]
instance [UpwardEnumerable α] :
Iterator (Rxi.Iterator α) Id α where
IsPlausibleStep it step := step = Iterator.Monadic.step it
step it := pure (.deflate ⟨Iterator.Monadic.step it, rfl⟩)
theorem Iterator.Monadic.isPlausibleStep_iff [UpwardEnumerable α]
{it : IterM (α := Rxi.Iterator α) Id α} {step} :
it.IsPlausibleStep step ↔ step = Iterator.Monadic.step it := by
exact Iff.rfl
theorem Iterator.Monadic.step_eq_step [UpwardEnumerable α]
{it : IterM (α := Rxi.Iterator α) Id α} :
it.step = pure (.deflate ⟨Iterator.Monadic.step it, isPlausibleStep_iff.mpr rfl⟩) := by
simp [IterM.step, Iterators.Iterator.step]
theorem Iterator.isPlausibleStep_iff [UpwardEnumerable α]
{it : Iter (α := Rxi.Iterator α) α} {step} :
it.IsPlausibleStep step ↔ step = Iterator.step it := by
simp only [Iter.IsPlausibleStep, Monadic.isPlausibleStep_iff, step_eq_monadicStep]
constructor
· intro h
generalize hs : (step.mapIterator Iter.toIterM) = stepM at h
cases h
replace hs := congrArg (IterStep.mapIterator IterM.toIter) hs
simpa using hs
· rintro rfl
simp only [IterStep.mapIterator_mapIterator, Iter.toIterM_comp_toIter, IterStep.mapIterator_id]
theorem Iterator.step_eq_step [UpwardEnumerable α]
{it : Iter (α := Rxi.Iterator α) α} :
it.step = ⟨Iterator.step it, isPlausibleStep_iff.mpr rfl⟩ := by
simp [Iter.step, step_eq_monadicStep, Monadic.step_eq_step, IterM.Step.toPure]
instance Iterator.instIteratorCollect [UpwardEnumerable α]
{n : Type u → Type w} [Monad n] : IteratorCollect (Rxi.Iterator α) Id n :=
.defaultImplementation
instance Iterator.instIteratorCollectPartial [UpwardEnumerable α]
{n : Type u → Type w} [Monad n] : IteratorCollectPartial (Rxi.Iterator α) Id n :=
.defaultImplementation
theorem Iterator.Monadic.isPlausibleOutput_next {a} [UpwardEnumerable α]
{it : IterM (α := Rxi.Iterator α) Id α} (h : it.internalState.next = some a) :
it.IsPlausibleOutput a := by
simp [IterM.IsPlausibleOutput, Monadic.isPlausibleStep_iff, Monadic.step, h]
theorem Iterator.Monadic.isPlausibleOutput_iff
[UpwardEnumerable α]
{it : IterM (α := Rxi.Iterator α) Id α} :
it.IsPlausibleOutput a ↔
it.internalState.next = some a := by
simp [IterM.IsPlausibleOutput, isPlausibleStep_iff, Monadic.step]
split
· simp [*]
· simp_all [eq_comm (a := a)]
theorem Iterator.isPlausibleOutput_next
[UpwardEnumerable α]
{it : Iter (α := Rxi.Iterator α) α} (h : it.internalState.next = some a) :
it.IsPlausibleOutput a := by
simp [Iter.IsPlausibleOutput, Monadic.isPlausibleOutput_iff, Iter.toIterM, h]
theorem Iterator.isPlausibleOutput_iff
[UpwardEnumerable α]
{it : Iter (α := Rxi.Iterator α) α} :
it.IsPlausibleOutput a ↔
it.internalState.next = some a := by
simp [Iter.IsPlausibleOutput, Monadic.isPlausibleOutput_iff, Iter.toIterM]
theorem Iterator.Monadic.isPlausibleSuccessorOf_iff
[UpwardEnumerable α]
{it' it : IterM (α := Rxi.Iterator α) Id α} :
it'.IsPlausibleSuccessorOf it ↔
∃ a, it.internalState.next = some a ∧
UpwardEnumerable.succ? a = it'.internalState.next := by
simp only [IterM.IsPlausibleSuccessorOf]
constructor
· rintro ⟨step, h, h'⟩
cases h'
simp only [Monadic.step] at h
split at h
· cases h
· cases h
simp_all
· rintro ⟨a, h, h'⟩
refine ⟨.yield it' a, rfl, ?_⟩
simp only [IterM.IsPlausibleStep, Iterator.IsPlausibleStep, step, h,
IterStep.yield.injEq, and_true]
simp [h']
theorem Iterator.isPlausibleSuccessorOf_iff
[UpwardEnumerable α]
{it' it : Iter (α := Rxi.Iterator α) α} :
it'.IsPlausibleSuccessorOf it ↔
∃ a, it.internalState.next = some a ∧
UpwardEnumerable.succ? a = it'.internalState.next := by
simp [Iter.IsPlausibleSuccessorOf, Monadic.isPlausibleSuccessorOf_iff, Iter.toIterM]
theorem Iterator.isSome_next_of_isPlausibleIndirectOutput
[UpwardEnumerable α]
{it : Iter (α := Rxi.Iterator α) α} {out : α} (h : it.IsPlausibleIndirectOutput out) :
it.internalState.next.isSome := by
cases h
case direct h =>
rw [isPlausibleOutput_iff] at h
simp [h]
case indirect h _ =>
rw [isPlausibleSuccessorOf_iff] at h
obtain ⟨a, ha, _⟩ := h
simp [ha]
private def Iterator.instFinitenessRelation [UpwardEnumerable α]
[LawfulUpwardEnumerable α] [Rxi.IsAlwaysFinite α] :
FinitenessRelation (Rxi.Iterator α) Id where
rel it' it := it'.IsPlausibleSuccessorOf it
wf := by
constructor
intro it
have hnone : Acc (fun it' it : IterM (α := Rxi.Iterator α) Id α => it'.IsPlausibleSuccessorOf it)
⟨⟨none⟩⟩ := by
constructor
intro it' ⟨step, hs₁, hs₂⟩
simp only [IterM.IsPlausibleStep, Iterator.IsPlausibleStep, Monadic.step] at hs₂
simp [hs₂, IterStep.successor] at hs₁
simp only [IterM.IsPlausibleSuccessorOf, IterM.IsPlausibleStep, Iterator.IsPlausibleStep,
Monadic.step, exists_eq_right] at hnone ⊢
match it with
| ⟨⟨none⟩⟩ => apply hnone
| ⟨⟨some init⟩⟩ =>
obtain ⟨n, hn⟩ := Rxi.IsAlwaysFinite.finite init
induction n generalizing init with
| zero => simp [succMany?_zero] at hn
| succ n ih =>
constructor
rintro it'
simp only [succMany?_add_one_eq_succ?_bind_succMany?] at hn
match hs : succ? init with
| none =>
simp only [hs]
intro h
cases h
apply hnone
| some a =>
intro h
simp only [hs] at h hn
specialize ih _ hn
cases h
exact ih
subrelation := id
@[no_expose]
instance Iterator.instFinite [UpwardEnumerable α]
[LawfulUpwardEnumerable α] [Rxi.IsAlwaysFinite α] :
Finite (Rxi.Iterator α) Id :=
.of_finitenessRelation instFinitenessRelation
private def Iterator.instProductivenessRelation [UpwardEnumerable α]
[LawfulUpwardEnumerable α] :
ProductivenessRelation (Rxi.Iterator α) Id where
rel := emptyWf.rel
wf := emptyWf.wf
subrelation {it it'} h := by
exfalso
simp only [IterM.IsPlausibleSkipSuccessorOf, IterM.IsPlausibleStep,
Iterator.IsPlausibleStep, Monadic.step] at h
split at h <;> cases h
@[no_expose]
instance Iterator.instProductive [UpwardEnumerable α]
[LawfulUpwardEnumerable α] :
Productive (Rxi.Iterator α) Id :=
.of_productivenessRelation instProductivenessRelation
instance Iterator.instIteratorAccess [UpwardEnumerable α]
[LawfulUpwardEnumerable α] :
IteratorAccess (Rxi.Iterator α) Id where
nextAtIdx? it n := ⟨match it.internalState.next.bind (UpwardEnumerable.succMany? n) with
| none => .done
| some next =>
.yield ⟨⟨UpwardEnumerable.succ? next⟩⟩ next, (by
induction n generalizing it
· split <;> rename_i heq
· apply IterM.IsPlausibleNthOutputStep.done
simp only [Monadic.isPlausibleStep_iff, Monadic.step]
simp only [Option.bind_eq_none_iff, succMany?_zero, reduceCtorEq,
imp_false] at heq
cases heq' : it.internalState.next
· simp
· rw [heq'] at heq
exfalso
exact heq _ rfl
· cases heq' : it.internalState.next
· simp [heq'] at heq
simp only [heq', Option.bind_some, succMany?_zero, Option.some.injEq] at heq
cases heq
· apply IterM.IsPlausibleNthOutputStep.zero_yield
simp [Monadic.isPlausibleStep_iff, Monadic.step, heq']
· rename_i n ih
split <;> rename_i heq
· cases heq' : it.internalState.next
· apply IterM.IsPlausibleNthOutputStep.done
simp only [Monadic.isPlausibleStep_iff, Monadic.step, heq']
· rename_i out
simp only [heq', Option.bind_some, succMany?_add_one_eq_succ?_bind_succMany?] at heq
specialize ih ⟨⟨UpwardEnumerable.succ? out⟩⟩
simp only [heq] at ih
· apply IterM.IsPlausibleNthOutputStep.yield
· simp only [Monadic.isPlausibleStep_iff, Monadic.step, heq',
IterStep.yield.injEq]
exact ⟨rfl, rfl⟩
· exact ih
· cases heq' : it.internalState.next
· simp [heq'] at heq
rename_i out
simp only [heq', Option.bind_some] at heq
have hlt : UpwardEnumerable.LT out _ := ⟨n, heq⟩
simp only [succMany?_add_one_eq_succ?_bind_succMany?] at heq
specialize ih ⟨⟨UpwardEnumerable.succ? out⟩⟩
simp only [heq] at ih
· apply IterM.IsPlausibleNthOutputStep.yield
· simp only [Monadic.isPlausibleStep_iff, Monadic.step, heq',
IterStep.yield.injEq]
exact ⟨rfl, rfl⟩
· apply ih)⟩
instance Iterator.instLawfulDeterministicIterator [UpwardEnumerable α] :
LawfulDeterministicIterator (Rxi.Iterator α) Id where
isPlausibleStep_eq_eq it := ⟨Monadic.step it, rfl⟩
theorem Iterator.Monadic.isPlausibleIndirectOutput_iff
[UpwardEnumerable α] [LawfulUpwardEnumerable α]
{it : IterM (α := Rxi.Iterator α) Id α} {out : α} :
it.IsPlausibleIndirectOutput out ↔
∃ n, it.internalState.next.bind (succMany? n ·) = some out := by
constructor
· intro h
induction h
case direct h =>
rw [Monadic.isPlausibleOutput_iff] at h
refine ⟨0, by simp [h, LawfulUpwardEnumerable.succMany?_zero]⟩
case indirect h _ ih =>
rw [Monadic.isPlausibleSuccessorOf_iff] at h
obtain ⟨n, hn⟩ := ih
obtain ⟨a, ha, h⟩ := h
refine ⟨n + 1, ?_⟩
simp [ha, succMany?_add_one_eq_succ?_bind_succMany?, hn, h]
· rintro ⟨n, hn⟩
induction n generalizing it
case zero =>
apply IterM.IsPlausibleIndirectOutput.direct
rw [Monadic.isPlausibleOutput_iff]
simpa [LawfulUpwardEnumerable.succMany?_zero] using hn
case succ ih =>
cases hn' : it.internalState.next
· simp [hn'] at hn
rename_i a
simp only [hn', Option.bind_some] at hn
have hlt : UpwardEnumerable.LT a out := ⟨_, hn⟩
rw [succMany?_add_one_eq_succ?_bind_succMany?] at hn
cases hn' : succ? a
· simp only [hn', Option.bind_none, reduceCtorEq] at hn
rename_i a'
simp only [hn', Option.bind_some] at hn
specialize ih (it := ⟨⟨some a'⟩⟩) hn
refine IterM.IsPlausibleIndirectOutput.indirect ?_ ih
rw [Monadic.isPlausibleSuccessorOf_iff]
exact ⟨a, _, hn'⟩
theorem Iterator.isPlausibleIndirectOutput_iff
[UpwardEnumerable α] [LawfulUpwardEnumerable α]
{it : Iter (α := Rxi.Iterator α) α} {out : α} :
it.IsPlausibleIndirectOutput out ↔
∃ n, it.internalState.next.bind (succMany? n ·) = some out := by
simp only [Iter.isPlausibleIndirectOutput_iff_isPlausibleIndirectOutput_toIterM,
Monadic.isPlausibleIndirectOutput_iff, Iter.toIterM]
section IteratorLoop
/--
An efficient {name}`IteratorLoop` instance:
As long as the compiler cannot optimize away the {name}`Option` in the internal state, we use a
special loop implementation.
-/
@[always_inline, inline]
instance Iterator.instIteratorLoop [UpwardEnumerable α]
[LawfulUpwardEnumerable α]
{n : Type u → Type w} [Monad n] :
IteratorLoop (Rxi.Iterator α) Id n where
forIn _ γ Pl wf it init f :=
match it with
| ⟨⟨some next⟩⟩ =>
loop γ Pl wf next init (fun a ha c => f a ?hf c) next ?hle
| ⟨⟨none⟩⟩ => return init
where
@[specialize]
loop γ Pl wf least acc
(f : (out : α) → UpwardEnumerable.LE least out → (c : γ) → n (Subtype (fun s : ForInStep γ => Pl out c s)))
(next : α) (hl : UpwardEnumerable.LE least next) : n γ := do
match ← f next hl acc with
| ⟨.yield acc', _⟩ =>
match hs : UpwardEnumerable.succ? next with
| some next' =>
loop γ Pl wf least acc' f next' ?hle'
| none => return acc'
| ⟨.done acc', _⟩ => return acc'
termination_by IteratorLoop.WithWF.mk ⟨⟨some next⟩⟩ acc (hwf := wf)
decreasing_by
simp [IteratorLoop.rel, Monadic.isPlausibleStep_iff,
Monadic.step, *]
finally
case hf =>
rw [Monadic.isPlausibleIndirectOutput_iff]
exact ha
case hle =>
exact UpwardEnumerable.le_refl _
case hle' =>
refine UpwardEnumerable.le_trans hl ⟨1, ?_⟩
simp [succMany?_one, hs]
/--
An efficient {name}`IteratorLoopPartial` instance:
As long as the compiler cannot optimize away the {name}`Option` in the internal state, we use a
special loop implementation.
-/
partial instance Iterator.instIteratorLoopPartial [UpwardEnumerable α]
[LawfulUpwardEnumerable α]
{n : Type u → Type w} [Monad n] : IteratorLoopPartial (Rxi.Iterator α) Id n where
forInPartial _ γ it init f :=
match it with
| ⟨⟨some next⟩⟩ => loop γ next init (fun a ha c => f a ?hf c) next ?hle
| ⟨⟨none⟩⟩ => return init
where
@[specialize]
loop γ least acc
(f : (out : α) → UpwardEnumerable.LE least out → (c : γ) → n (ForInStep γ))
(next : α) (hl : UpwardEnumerable.LE least next) : n γ := do
match ← f next hl acc with
| .yield acc' =>
match hs : succ? next with
| some next' =>
loop γ least acc' f next' ?hle'
| none => return acc'
| .done acc' => return acc'
finally
case hf =>
rw [Monadic.isPlausibleIndirectOutput_iff]
exact ha
case hle =>
exact UpwardEnumerable.le_refl _
case hle' =>
refine UpwardEnumerable.le_trans hl ⟨1, ?_⟩
simp [succMany?_one, hs]
theorem Iterator.instIteratorLoop.loop_eq [UpwardEnumerable α]
[LawfulUpwardEnumerable α]
{n : Type u → Type w} [Monad n] [LawfulMonad n] {γ : Type u}
{lift} [Internal.LawfulMonadLiftBindFunction lift]
{PlausibleForInStep next hl f acc wf} :
loop (α := α) (n := n) γ PlausibleForInStep wf least acc f next hl =
(do
match ← f next hl acc with
| ⟨.yield c, _⟩ =>
letI it' : IterM (α := Rxi.Iterator α) Id α := ⟨⟨succ? next⟩⟩
IterM.DefaultConsumers.forIn' (m := Id) lift γ
PlausibleForInStep wf it' c it'.IsPlausibleIndirectOutput (fun _ => id)
(fun b h c => f b
(by
refine UpwardEnumerable.le_trans hl ?_
simp only [Monadic.isPlausibleIndirectOutput_iff, it',
← succMany?_add_one_eq_succ?_bind_succMany?] at h
exact ⟨h.choose + 1, h.choose_spec⟩)
c)
| ⟨.done c, _⟩ => return c) := by
rw [loop]
apply bind_congr
intro step
split
· split
· split
· rename_i heq
cases heq
simp only [*]
rw [IterM.DefaultConsumers.forIn']
simp only [Monadic.step_eq_step, Monadic.step, *,
Internal.LawfulMonadLiftBindFunction.liftBind_pure]
rw [loop_eq (lift := lift), Shrink.inflate_deflate]
apply bind_congr
intro step
split
· apply IterM.DefaultConsumers.forIn'_eq_forIn'
intros; rfl
· simp
· rename_i heq
cases heq
· simp only [*]
rw [IterM.DefaultConsumers.forIn']
simp [Monadic.step_eq_step, Monadic.step, Internal.LawfulMonadLiftBindFunction.liftBind_pure]
· simp
termination_by IteratorLoop.WithWF.mk ⟨⟨some next⟩⟩ acc (hwf := wf)
decreasing_by
simp [IteratorLoop.rel, Monadic.isPlausibleStep_iff, Monadic.step, *]
instance Iterator.instLawfulIteratorLoop [UpwardEnumerable α]
[LawfulUpwardEnumerable α] {n : Type u → Type w} [Monad n] [LawfulMonad n] :
LawfulIteratorLoop (Rxi.Iterator α) Id n where
lawful := by
intro lift instLawfulMonadLiftFunction
ext γ PlausibleForInStep hwf it init f
simp only [IteratorLoop.forIn, IteratorLoop.defaultImplementation]
rw [IterM.DefaultConsumers.forIn']
simp only [Monadic.step_eq_step, Monadic.step]
simp only [Internal.LawfulMonadLiftBindFunction.liftBind_pure]
split
· rename_i it f next upperBound f'
rw [instIteratorLoop.loop_eq (lift := lift), Shrink.inflate_deflate]
apply bind_congr
intro step
split
· apply IterM.DefaultConsumers.forIn'_eq_forIn'
intro b c hPb hQb
congr
· simp
· simp
end IteratorLoop
end Rxi
end Std