|
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 | 1 | prelude |
7 | | -import Iterator.Basic |
8 | | -import Iterator.Consumers.Collect |
9 | | -import Iterator.Consumers.Loop |
| 2 | +import Iterator.Combinators.Monadic.Drop |
| 3 | +import Iterator.Pure |
10 | 4 |
|
11 | | -/-! |
12 | | -This file provides the iterator combinator `IterM.drop`. |
13 | | --/ |
14 | | - |
15 | | -variable {α : Type w} {m : Type w → Type w'} {β : Type v} |
16 | | - |
17 | | -structure Drop (α : Type w) (m : Type w → Type w') (β : Type v) where |
18 | | - remaining : Nat |
19 | | - inner : IterM (α := α) m β |
20 | | - |
21 | | -/-- |
22 | | -Given an iterator `it` and a natural number `n`, `it.drop n` is an iterator that forwards all of |
23 | | -`it`'s output values except for the first `n`. |
24 | | -
|
25 | | -**Marble diagram:** |
26 | | -
|
27 | | -```text |
28 | | -it ---a----b---c--d-e--⊥ |
29 | | -it.drop 3 ---------------d-e--⊥ |
30 | | -
|
31 | | -it ---a--⊥ |
32 | | -it.drop 3 ------⊥ |
33 | | -``` |
34 | | -
|
35 | | -**Termination properties:** |
36 | | -
|
37 | | -* `Finite` instance: only if `it` is finite |
38 | | -* `Productive` instance: only if `it` is productive |
39 | | -
|
40 | | -_TODO_: prove `Productive` |
41 | | -
|
42 | | -**Performance:** |
43 | | -
|
44 | | -Currently, this combinator incurs an additional O(1) cost with each output of `it`, even when the iterator |
45 | | -does not drop any elements anymore. |
46 | | --/ |
47 | | -def IterM.drop (n : Nat) (it : IterM (α := α) m β) := |
48 | | - toIter (Drop.mk n it) m β |
49 | | - |
50 | | -inductive Drop.PlausibleStep [Iterator α m β] (it : IterM (α := Drop α m β) m β) : |
51 | | - (step : IterStep (IterM (α := Drop α m β) m β) β) → Prop where |
52 | | - | drop : ∀ {it' out k}, it.inner.inner.plausible_step (.yield it' out) → |
53 | | - it.inner.remaining = k + 1 → PlausibleStep it (.skip (it'.drop k)) |
54 | | - | skip : ∀ {it'}, it.inner.inner.plausible_step (.skip it') → |
55 | | - PlausibleStep it (.skip (it'.drop it.inner.remaining)) |
56 | | - | done : it.inner.inner.plausible_step .done → PlausibleStep it .done |
57 | | - | yield : ∀ {it' out}, it.inner.inner.plausible_step (.yield it' out) → |
58 | | - it.inner.remaining = 0 → PlausibleStep it (.yield (it'.drop 0) out) |
59 | | - |
60 | | -def Drop.step [Monad m] [Iterator α m β] (it : IterM (α := Drop α m β) m β) : |
61 | | - HetT m (IterStep (IterM (α := Drop α m β) m β) β) := do |
62 | | - match ← it.inner.inner.stepHet with |
63 | | - | .yield it' out => |
64 | | - match it.inner.remaining with |
65 | | - | 0 => return .yield (it'.drop 0) out |
66 | | - | k + 1 => return .skip (it'.drop k) |
67 | | - | .skip it' => return .skip (it'.drop it.inner.remaining) |
68 | | - | .done => return .done |
69 | | - |
70 | | -theorem Drop.PlausibleStep.char [Monad m] [Iterator α m β] {it : IterM (α := Drop α m β) m β} : |
71 | | - Drop.PlausibleStep it = (Drop.step it).property := by |
72 | | - ext step |
73 | | - simp only [Drop.step, bind, HetT.bindH] |
74 | | - constructor |
75 | | - · intro h |
76 | | - cases h |
77 | | - all_goals |
78 | | - refine ⟨_, ‹_›, ?_⟩ |
79 | | - simp_all [pure] |
80 | | - · rintro ⟨step, hp, h⟩ |
81 | | - cases step |
82 | | - case yield => |
83 | | - dsimp only at h |
84 | | - split at h |
85 | | - · cases h |
86 | | - exact .yield hp ‹_› |
87 | | - · cases h |
88 | | - exact .drop hp ‹_› |
89 | | - case skip => |
90 | | - cases h |
91 | | - exact .skip hp |
92 | | - case done => |
93 | | - cases h |
94 | | - exact .done hp |
95 | | - |
96 | | -instance [Monad m] [Iterator α m β] {it : IterM (α := Drop α m β) m β} : |
97 | | - Small.{w} (Subtype <| Drop.PlausibleStep it) := by |
98 | | - rw [Drop.PlausibleStep.char] |
99 | | - exact (Drop.step it).small |
100 | | - |
101 | | -instance Drop.instIterator [Monad m] [Iterator α m β] : Iterator (Drop α m β) m β where |
102 | | - plausible_step := Drop.PlausibleStep |
103 | | - step_small := inferInstance |
104 | | - step it := do |
105 | | - match (← it.inner.inner.stepH).inflate (small := _) with |
106 | | - | .yield it' out h => |
107 | | - match h' : it.inner.remaining with |
108 | | - | 0 => pure <| .deflate <| .yield (it'.drop 0) out (.yield h h') |
109 | | - | k + 1 => pure <| .deflate <| .skip (it'.drop k) (.drop h h') |
110 | | - | .skip it' h => |
111 | | - pure <| .deflate <| .skip (it'.drop it.inner.remaining) (.skip h) |
112 | | - | .done h => |
113 | | - pure <| .deflate <| .done (.done h) |
114 | | - |
115 | | -def Drop.rel (m : Type w → Type w') [Iterator α m β] [Finite α m] : |
116 | | - IterM (α := Drop α m β) m β → IterM (α := Drop α m β) m β → Prop := |
117 | | - InvImage IterM.TerminationMeasures.Finite.rel (IterM.finitelyManySteps ∘ Drop.inner ∘ IterM.inner) |
118 | | - |
119 | | -instance Drop.instFinitenessRelation [Iterator α m β] [Monad m] [Finite α m] : |
120 | | - FinitenessRelation (Drop α m β) m where |
121 | | - rel := Drop.rel m |
122 | | - wf := by |
123 | | - apply InvImage.wf |
124 | | - exact WellFoundedRelation.wf |
125 | | - subrelation {it it'} h := by |
126 | | - obtain ⟨step, h, h'⟩ := h |
127 | | - cases h' |
128 | | - case drop it' h' _ => |
129 | | - cases h |
130 | | - apply IterM.TerminationMeasures.Finite.rel_of_yield |
131 | | - exact h' |
132 | | - case skip it' h' => |
133 | | - cases h |
134 | | - apply IterM.TerminationMeasures.Finite.rel_of_skip |
135 | | - exact h' |
136 | | - case done h' => |
137 | | - cases h |
138 | | - case yield it' out h' h'' => |
139 | | - cases h |
140 | | - apply IterM.TerminationMeasures.Finite.rel_of_yield |
141 | | - exact h' |
142 | | - |
143 | | -instance Drop.instIteratorToArray [Monad m] [Iterator α m β] [Finite α m] : IteratorToArray (Drop α m β) m := |
144 | | - .defaultImplementation |
145 | | - |
146 | | -instance Drop.instIteratorFor [Monad m] [Monad n] [Iterator α m β] [Finite α m] : |
147 | | - IteratorFor (Drop α m β) m n := |
148 | | - .defaultImplementation |
| 5 | +@[always_inline, inline] |
| 6 | +def Iter.drop {α : Type w} {β : Type v} (n : Nat) (it : Iter (α := α) β) : |
| 7 | + Iter (α := Drop α Id β) β := |
| 8 | + it.toIterM.drop n |>.toPureIter |
0 commit comments