This PR moves parts of the iterator library from `Std` to `Init`. The reason is that the polymorphic range API must be in `Init` and it depends on the iterators.
169 lines
6 KiB
Text
169 lines
6 KiB
Text
/-
|
||
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 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`.
|
||
-/
|
||
|
||
namespace Std.Iterators
|
||
|
||
variable {α : Type w} {m : Type w → Type w'} {β : Type w}
|
||
|
||
/--
|
||
The internal state of the `IterM.drop` combinator.
|
||
-/
|
||
@[unbox]
|
||
structure Drop (α : Type w) (m : Type w → Type w') (β : Type w) where
|
||
/-- Internal implementation detail of the iterator library -/
|
||
remaining : Nat
|
||
/-- Internal implementation detail of the iterator library -/
|
||
inner : IterM (α := α) m β
|
||
|
||
/--
|
||
Given an iterator `it` and a natural number `n`, `it.drop n` is an iterator that forwards all of
|
||
`it`'s output values except for the first `n`.
|
||
|
||
**Marble diagram:**
|
||
|
||
```text
|
||
it ---a----b---c--d-e--⊥
|
||
it.drop 3 ---------------d-e--⊥
|
||
|
||
it ---a--⊥
|
||
it.drop 3 ------⊥
|
||
```
|
||
|
||
**Termination properties:**
|
||
|
||
* `Finite` instance: only if `it` is finite
|
||
* `Productive` instance: only if `it` is productive
|
||
|
||
**Performance:**
|
||
|
||
Currently, this combinator incurs an additional O(1) cost with each output of `it`, even when the iterator
|
||
does not drop any elements anymore.
|
||
-/
|
||
@[always_inline, inline]
|
||
def IterM.drop (n : Nat) (it : IterM (α := α) m β) :=
|
||
toIterM (Drop.mk n it) m β
|
||
|
||
inductive Drop.PlausibleStep [Iterator α m β] (it : IterM (α := Drop α m β) m β) :
|
||
(step : IterStep (IterM (α := Drop α m β) m β) β) → Prop where
|
||
| drop : ∀ {it' out k}, it.internalState.inner.IsPlausibleStep (.yield it' out) →
|
||
it.internalState.remaining = k + 1 → PlausibleStep it (.skip (it'.drop k))
|
||
| skip : ∀ {it'}, it.internalState.inner.IsPlausibleStep (.skip it') →
|
||
PlausibleStep it (.skip (it'.drop it.internalState.remaining))
|
||
| done : it.internalState.inner.IsPlausibleStep .done → PlausibleStep it .done
|
||
| yield : ∀ {it' out}, it.internalState.inner.IsPlausibleStep (.yield it' out) →
|
||
it.internalState.remaining = 0 → PlausibleStep it (.yield (it'.drop 0) out)
|
||
|
||
instance Drop.instIterator [Monad m] [Iterator α m β] : Iterator (Drop α m β) m β where
|
||
IsPlausibleStep := Drop.PlausibleStep
|
||
step it := do
|
||
match ← it.internalState.inner.step with
|
||
| .yield it' out h =>
|
||
match h' : it.internalState.remaining with
|
||
| 0 => pure <| .yield (it'.drop 0) out (.yield h h')
|
||
| k + 1 => pure <| .skip (it'.drop k) (.drop h h')
|
||
| .skip it' h =>
|
||
pure <| .skip (it'.drop it.internalState.remaining) (.skip h)
|
||
| .done h =>
|
||
pure <| .done (.done h)
|
||
|
||
private def Drop.FiniteRel (m : Type w → Type w') [Iterator α m β] [Finite α m] :
|
||
IterM (α := Drop α m β) m β → IterM (α := Drop α m β) m β → Prop :=
|
||
InvImage IterM.TerminationMeasures.Finite.Rel
|
||
(IterM.finitelyManySteps ∘ Drop.inner ∘ IterM.internalState)
|
||
|
||
private def Drop.instFinitenessRelation [Iterator α m β] [Monad m]
|
||
[Finite α m] :
|
||
FinitenessRelation (Drop α m β) m where
|
||
rel := Drop.FiniteRel m
|
||
wf := by
|
||
apply InvImage.wf
|
||
exact WellFoundedRelation.wf
|
||
subrelation {it it'} h := by
|
||
obtain ⟨step, h, h'⟩ := h
|
||
cases h'
|
||
case drop it' h' _ =>
|
||
cases h
|
||
apply IterM.TerminationMeasures.Finite.rel_of_yield
|
||
exact h'
|
||
case skip it' h' =>
|
||
cases h
|
||
apply IterM.TerminationMeasures.Finite.rel_of_skip
|
||
exact h'
|
||
case done h' =>
|
||
cases h
|
||
case yield it' out h' h'' =>
|
||
cases h
|
||
apply IterM.TerminationMeasures.Finite.rel_of_yield
|
||
exact h'
|
||
|
||
instance Drop.instFinite [Iterator α m β] [Monad m] [Finite α m] :
|
||
Finite (Drop α m β) m :=
|
||
Finite.of_finitenessRelation instFinitenessRelation
|
||
|
||
private def Drop.ProductiveRel (m : Type w → Type w') [Iterator α m β] [Productive α m] :
|
||
IterM (α := Drop α m β) m β → IterM (α := Drop α m β) m β → Prop :=
|
||
InvImage (Prod.Lex Nat.lt_wfRel.rel IterM.TerminationMeasures.Productive.Rel)
|
||
(fun it => (it.internalState.remaining, it.internalState.inner.finitelyManySkips))
|
||
|
||
private theorem Drop.productiveRel_of_remaining [Monad m] [Iterator α m β] [Productive α m]
|
||
{it it' : IterM (α := Drop α m β) m β}
|
||
(h : it'.internalState.remaining < it.internalState.remaining) : Drop.ProductiveRel m it' it :=
|
||
Prod.Lex.left _ _ h
|
||
|
||
private theorem Drop.productiveRel_of_inner [Monad m] [Iterator α m β] [Productive α m] {remaining : Nat}
|
||
{it it' : IterM (α := α) m β}
|
||
(h : it'.finitelyManySkips.Rel it.finitelyManySkips) :
|
||
Drop.ProductiveRel m (it'.drop remaining) (it.drop remaining) :=
|
||
Prod.Lex.right _ h
|
||
|
||
private def Drop.instProductivenessRelation [Iterator α m β] [Monad m]
|
||
[Productive α m] :
|
||
ProductivenessRelation (Drop α m β) m where
|
||
rel := Drop.ProductiveRel m
|
||
wf := by
|
||
apply InvImage.wf
|
||
exact WellFoundedRelation.wf
|
||
subrelation {it it'} h := by
|
||
rw [IterM.IsPlausibleSkipSuccessorOf] at h
|
||
cases h
|
||
case drop it' out k h h' =>
|
||
apply productiveRel_of_remaining
|
||
simp [h', IterM.drop]
|
||
case skip it' h =>
|
||
apply productiveRel_of_inner
|
||
apply IterM.TerminationMeasures.Productive.rel_of_skip
|
||
exact h
|
||
|
||
instance Drop.instProductive [Iterator α m β] [Monad m] [Productive α m] :
|
||
Productive (Drop α m β) m :=
|
||
Productive.of_productivenessRelation instProductivenessRelation
|
||
|
||
instance Drop.instIteratorCollect [Monad m] [Monad n] [Iterator α m β] [Finite α m] :
|
||
IteratorCollect (Drop α m β) m n :=
|
||
.defaultImplementation
|
||
|
||
instance Drop.instIteratorCollectPartial [Monad m] [Monad n] [Iterator α m β] :
|
||
IteratorCollectPartial (Drop α m β) m n :=
|
||
.defaultImplementation
|
||
|
||
instance Drop.instIteratorLoop [Monad m] [Monad n] [Iterator α m β] :
|
||
IteratorLoop (Drop α m β) m n :=
|
||
.defaultImplementation
|
||
|
||
instance Drop.instIteratorLoopPartial [Monad m] [Monad n] [Iterator α m β] :
|
||
IteratorLoopPartial (Drop α m β) m n :=
|
||
.defaultImplementation
|
||
|
||
end Std.Iterators
|