lean4-htt/src/Init/Data/Iterators/Lemmas/Consumers/Collect.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

160 lines
6.5 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.Lemmas.Basic
public import Init.Data.Iterators.Lemmas.Consumers.Monadic.Collect
public import Init.Data.Iterators.Consumers.Access
import all Init.Data.Iterators.Consumers.Access
public import Init.Data.Iterators.Consumers.Collect
import all Init.Data.Iterators.Consumers.Collect
public section
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)
@[simp]
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]
@[simp]
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.val 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.inflate 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.val 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.val 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.inflate 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]
theorem Iter.isPlausibleIndirectOutput_of_mem_toList
[Iterator α Id β] [Finite α Id] [IteratorCollect α Id Id] [LawfulIteratorCollect α Id Id]
{it : Iter (α := α) β} {b : β} :
b ∈ it.toList → it.IsPlausibleIndirectOutput b := by
induction it using Iter.inductSteps with | step it ihy ihs
rw [toList_eq_match_step]
cases it.step using PlausibleIterStep.casesOn
case yield it' out h =>
simp only [List.mem_cons]
rintro h'
cases h' <;> rename_i h'
· cases h'
exact .direct ⟨_, h⟩
· specialize ihy h h'
exact IsPlausibleIndirectOutput.indirect ⟨_, rfl, h⟩ ihy
case skip it' h =>
simp only
intro h'
specialize ihs h h'
exact IsPlausibleIndirectOutput.indirect ⟨_, rfl, h⟩ ihs
case done h =>
simp
theorem Iter.isPlausibleIndirectOutput_of_mem_toListRev
[Iterator α Id β] [Finite α Id] [IteratorCollect α Id Id] [LawfulIteratorCollect α Id Id]
{it : Iter (α := α) β} {b : β} :
b ∈ it.toListRev → it.IsPlausibleIndirectOutput b := by
intro h
apply isPlausibleIndirectOutput_of_mem_toList
simpa [toListRev_eq] using h
theorem Iter.isPlausibleIndirectOutput_of_mem_toArray
[Iterator α Id β] [Finite α Id] [IteratorCollect α Id Id] [LawfulIteratorCollect α Id Id]
{it : Iter (α := α) β} {b : β} :
b ∈ it.toArray → it.IsPlausibleIndirectOutput b := by
intro h
apply isPlausibleIndirectOutput_of_mem_toList
rw [← Array.mem_toList_iff] at h
simpa [toList_toArray] using h
end Std.Iterators