|
| 1 | +/- |
| 2 | +Copyright (c) 2025 Lean FRO, LLC. All rights reserved. |
| 3 | +Released under Apache 2.0 license as described in the file LICENSE. |
| 4 | +Authors: Paul Reichert |
| 5 | +-/ |
| 6 | +prelude |
| 7 | +import Std.Data.Iterators.Basic |
| 8 | +import Std.Data.Iterators.Consumers.Collect |
| 9 | +import Std.Data.Iterators.Consumers.Loop |
| 10 | +import Std.Data.Iterators.Internal.Termination |
| 11 | + |
| 12 | +/-! |
| 13 | +This file provides the iterator combinator `IterM.drop`. |
| 14 | +-/ |
| 15 | + |
| 16 | +namespace Std.Iterators |
| 17 | + |
| 18 | +variable {α : Type w} {m : Type w → Type w'} {β : Type w} |
| 19 | + |
| 20 | +structure Drop (α : Type w) (m : Type w → Type w') (β : Type w) where |
| 21 | + remaining : Nat |
| 22 | + inner : IterM (α := α) m β |
| 23 | + |
| 24 | +/-- |
| 25 | +Given an iterator `it` and a natural number `n`, `it.drop n` is an iterator that forwards all of |
| 26 | +`it`'s output values except for the first `n`. |
| 27 | +
|
| 28 | +**Marble diagram:** |
| 29 | +
|
| 30 | +```text |
| 31 | +it ---a----b---c--d-e--⊥ |
| 32 | +it.drop 3 ---------------d-e--⊥ |
| 33 | +
|
| 34 | +it ---a--⊥ |
| 35 | +it.drop 3 ------⊥ |
| 36 | +``` |
| 37 | +
|
| 38 | +**Termination properties:** |
| 39 | +
|
| 40 | +* `Finite` instance: only if `it` is finite |
| 41 | +* `Productive` instance: only if `it` is productive |
| 42 | +
|
| 43 | +_TODO_: prove `Productive` |
| 44 | +
|
| 45 | +**Performance:** |
| 46 | +
|
| 47 | +Currently, this combinator incurs an additional O(1) cost with each output of `it`, even when the iterator |
| 48 | +does not drop any elements anymore. |
| 49 | +-/ |
| 50 | +def IterM.drop (n : Nat) (it : IterM (α := α) m β) := |
| 51 | + toIterM (Drop.mk n it) m β |
| 52 | + |
| 53 | +inductive Drop.PlausibleStep [Iterator α m β] (it : IterM (α := Drop α m β) m β) : |
| 54 | + (step : IterStep (IterM (α := Drop α m β) m β) β) → Prop where |
| 55 | + | drop : ∀ {it' out k}, it.internalState.inner.IsPlausibleStep (.yield it' out) → |
| 56 | + it.internalState.remaining = k + 1 → PlausibleStep it (.skip (it'.drop k)) |
| 57 | + | skip : ∀ {it'}, it.internalState.inner.IsPlausibleStep (.skip it') → |
| 58 | + PlausibleStep it (.skip (it'.drop it.internalState.remaining)) |
| 59 | + | done : it.internalState.inner.IsPlausibleStep .done → PlausibleStep it .done |
| 60 | + | yield : ∀ {it' out}, it.internalState.inner.IsPlausibleStep (.yield it' out) → |
| 61 | + it.internalState.remaining = 0 → PlausibleStep it (.yield (it'.drop 0) out) |
| 62 | + |
| 63 | +instance Drop.instIterator [Monad m] [Iterator α m β] : Iterator (Drop α m β) m β where |
| 64 | + IsPlausibleStep := Drop.PlausibleStep |
| 65 | + step it := do |
| 66 | + match ← it.internalState.inner.step with |
| 67 | + | .yield it' out h => |
| 68 | + match h' : it.internalState.remaining with |
| 69 | + | 0 => pure <| .yield (it'.drop 0) out (.yield h h') |
| 70 | + | k + 1 => pure <| .skip (it'.drop k) (.drop h h') |
| 71 | + | .skip it' h => |
| 72 | + pure <| .skip (it'.drop it.internalState.remaining) (.skip h) |
| 73 | + | .done h => |
| 74 | + pure <| .done (.done h) |
| 75 | + |
| 76 | +private def Drop.FiniteRel (m : Type w → Type w') [Iterator α m β] [Finite α m] : |
| 77 | + IterM (α := Drop α m β) m β → IterM (α := Drop α m β) m β → Prop := |
| 78 | + InvImage IterM.TerminationMeasures.Finite.Rel |
| 79 | + (IterM.finitelyManySteps ∘ Drop.inner ∘ IterM.internalState) |
| 80 | + |
| 81 | +private def Drop.instFinitenessRelation [Iterator α m β] [Monad m] |
| 82 | + [Finite α m] : |
| 83 | + FinitenessRelation (Drop α m β) m where |
| 84 | + rel := Drop.FiniteRel m |
| 85 | + wf := by |
| 86 | + apply InvImage.wf |
| 87 | + exact WellFoundedRelation.wf |
| 88 | + subrelation {it it'} h := by |
| 89 | + obtain ⟨step, h, h'⟩ := h |
| 90 | + cases h' |
| 91 | + case drop it' h' _ => |
| 92 | + cases h |
| 93 | + apply IterM.TerminationMeasures.Finite.rel_of_yield |
| 94 | + exact h' |
| 95 | + case skip it' h' => |
| 96 | + cases h |
| 97 | + apply IterM.TerminationMeasures.Finite.rel_of_skip |
| 98 | + exact h' |
| 99 | + case done h' => |
| 100 | + cases h |
| 101 | + case yield it' out h' h'' => |
| 102 | + cases h |
| 103 | + apply IterM.TerminationMeasures.Finite.rel_of_yield |
| 104 | + exact h' |
| 105 | + |
| 106 | +instance Drop.instFinite [Iterator α m β] [Monad m] [Finite α m] : |
| 107 | + Finite (Drop α m β) m := |
| 108 | + Finite.of_finitenessRelation instFinitenessRelation |
| 109 | + |
| 110 | +private def Drop.ProductiveRel (m : Type w → Type w') [Iterator α m β] [Productive α m] : |
| 111 | + IterM (α := Drop α m β) m β → IterM (α := Drop α m β) m β → Prop := |
| 112 | + InvImage (Prod.Lex Nat.lt_wfRel.rel IterM.TerminationMeasures.Productive.Rel) |
| 113 | + (fun it => (it.internalState.remaining, it.internalState.inner.finitelyManySkips)) |
| 114 | + |
| 115 | +private theorem Drop.productiveRel_of_remaining [Monad m] [Iterator α m β] [Productive α m] |
| 116 | + {it it' : IterM (α := Drop α m β) m β} |
| 117 | + (h : it'.internalState.remaining < it.internalState.remaining) : Drop.ProductiveRel m it' it := |
| 118 | + Prod.Lex.left _ _ h |
| 119 | + |
| 120 | +private theorem Drop.productiveRel_of_inner [Monad m] [Iterator α m β] [Productive α m] {remaining : Nat} |
| 121 | + {it it' : IterM (α := α) m β} |
| 122 | + (h : it'.finitelyManySkips.Rel it.finitelyManySkips) : |
| 123 | + Drop.ProductiveRel m (it'.drop remaining) (it.drop remaining) := |
| 124 | + Prod.Lex.right _ h |
| 125 | + |
| 126 | +private def Drop.instProductivenessRelation [Iterator α m β] [Monad m] |
| 127 | + [Productive α m] : |
| 128 | + ProductivenessRelation (Drop α m β) m where |
| 129 | + rel := Drop.ProductiveRel m |
| 130 | + wf := by |
| 131 | + apply InvImage.wf |
| 132 | + exact WellFoundedRelation.wf |
| 133 | + subrelation {it it'} h := by |
| 134 | + rw [IterM.IsPlausibleSkipSuccessorOf] at h |
| 135 | + cases h |
| 136 | + case drop it' out k h h' => |
| 137 | + apply productiveRel_of_remaining |
| 138 | + simp [h', IterM.drop] |
| 139 | + case skip it' h => |
| 140 | + apply productiveRel_of_inner |
| 141 | + apply IterM.TerminationMeasures.Productive.rel_of_skip |
| 142 | + exact h |
| 143 | + |
| 144 | +instance Drop.instProductive [Iterator α m β] [Monad m] [Productive α m] : |
| 145 | + Productive (Drop α m β) m := |
| 146 | + Productive.of_productivenessRelation instProductivenessRelation |
| 147 | + |
| 148 | +instance Drop.instIteratorCollect [Monad m] [Iterator α m β] [Finite α m] : |
| 149 | + IteratorCollect (Drop α m β) m := |
| 150 | + .defaultImplementation |
| 151 | + |
| 152 | +instance Drop.instIteratorCollectPartial [Monad m] [Iterator α m β] : |
| 153 | + IteratorCollectPartial (Drop α m β) m := |
| 154 | + .defaultImplementation |
| 155 | + |
| 156 | +instance Drop.instIteratorLoop [Monad m] [Monad n] [Iterator α m β] : |
| 157 | + IteratorLoop (Drop α m β) m n := |
| 158 | + .defaultImplementation |
| 159 | + |
| 160 | +instance Drop.instIteratorLoopPartial [Monad m] [Monad n] [Iterator α m β] : |
| 161 | + IteratorLoopPartial (Drop α m β) m n := |
| 162 | + .defaultImplementation |
| 163 | + |
| 164 | +end Std.Iterators |
0 commit comments