Skip to content

Commit 100f509

Browse files
committed
monadic drop; todo: iteratorFor
1 parent dbafe1f commit 100f509

File tree

1 file changed

+164
-0
lines changed
  • src/Std/Data/Iterators/Combinators/Monadic

1 file changed

+164
-0
lines changed
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
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

Comments
 (0)