Skip to content
This repository was archived by the owner on Aug 22, 2025. It is now read-only.

Commit 42afba5

Browse files
committed
use pure iterators in examples
1 parent 29b35a6 commit 42afba5

File tree

15 files changed

+92
-52
lines changed

15 files changed

+92
-52
lines changed

Iterator.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
-- This module serves as the root of the `Iterator` library.
22
-- Import modules here that should be built as part of the library.
33
import Iterator.Basic
4+
import Iterator.Pure
45
import Iterator.Producers
56
import Iterator.Combinators
67
import Iterator.Consumers

Iterator/Combinators/Drop.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,6 @@ instance Drop.instFinitenessRelation [Iterator α m β] [Monad m] [Finite α m]
143143
instance Drop.instIteratorToArray [Monad m] [Iterator α m β] [Finite α m] : IteratorToArray (Drop α m β) m :=
144144
.defaultImplementation
145145

146-
instance Drop.instIteratorFor [Monad m] [Monad n] [MonadLiftT m n] [Iterator α m β] [Finite α m] :
146+
instance Drop.instIteratorFor [Monad m] [Monad n] [Iterator α m β] [Finite α m] :
147147
IteratorFor (Drop α m β) m n :=
148148
.defaultImplementation

Iterator/Combinators/FilterMap.lean

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ instance {f : β → HetT m (Option γ)} [Finite α m] :
176176
IteratorToArray (FilterMapMH α f) m :=
177177
.defaultImplementation
178178

179-
instance FilterMapMH.instIteratorFor [Monad m] [Monad n] [MonadLiftT m n]
179+
instance FilterMapMH.instIteratorFor [Monad m] [Monad n]
180180
[Iterator α m β] [Finite α m] :
181181
IteratorFor (FilterMapMH α f) m n :=
182182
.defaultImplementation
@@ -192,7 +192,7 @@ instance {f : β → HetT m γ} [IteratorToArray α m] :
192192
(fun x => do g ((← (f x).computation).inflate (small := _)))
193193
it.inner.inner
194194

195-
instance MapMH.instIteratorFor [Monad m] [Monad n] [MonadLiftT m n]
195+
instance MapMH.instIteratorFor [Monad m] [Monad n]
196196
[Iterator α m β] [Finite α m] :
197197
IteratorFor (MapMH α f) m n :=
198198
.defaultImplementation

Iterator/Combinators/FlatMap.lean

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,7 @@ instance FlatMap.instIteratorToArray [Monad m] [Iterator α₂ m γ] [Finite α
340340
IteratorToArray (FlatMap α f) m :=
341341
.defaultImplementation
342342

343-
instance FlatMap.instIteratorFor [Monad m] [Monad n] [MonadLiftT m n] [Iterator α₂ m γ]
343+
instance FlatMap.instIteratorFor [Monad m] [Monad n] [Iterator α₂ m γ]
344344
[Finite α m] [Finite α₂ m] :
345345
IteratorFor (FlatMap α f) m n :=
346346
.defaultImplementation
@@ -453,7 +453,7 @@ instance SigmaIterator.instIteratorToArray [Monad m] [∀ b, Iterator (α b) m
453453
IteratorToArray (SigmaIterator α m γ) m :=
454454
.defaultImplementation
455455

456-
instance SigmaIterator.instIteratorFor [Monad m] [Monad n] [MonadLiftT m n]
456+
instance SigmaIterator.instIteratorFor [Monad m] [Monad n]
457457
[∀ b, Iterator (α b) m γ] [∀ b, Finite (α b) m] :
458458
IteratorFor (SigmaIterator α m γ) m n :=
459459
.defaultImplementation

Iterator/Combinators/MonadLift.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ instance {_ : Iterator α m β} [Finite α m] {_ : MonadLiftT m n} : FinitenessR
5252
case done h =>
5353
cases h
5454

55-
instance MonadLiftIterator.instIteratorFor [Monad n] [Monad n'] [MonadLiftT n n']
55+
instance MonadLiftIterator.instIteratorFor [Monad n] [Monad n']
5656
[Iterator α m β] [Finite α m] {_ : MonadLiftT m n} :
5757
IteratorFor (MonadLiftIterator α m n) n n' :=
5858
.defaultImplementation

Iterator/Combinators/Take.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ instance Take.instFinitenessRelation [Monad m] [Iterator α m β] [Productive α
168168
instance Take.instIteratorToArray [Monad m] [Iterator α m β] [Productive α m] : IteratorToArray (Take α m β) m :=
169169
.defaultImplementation
170170

171-
instance Take.instIteratorFor [Monad m] [Monad n] [MonadLiftT m n] [Iterator α m β] [Finite α m] :
171+
instance Take.instIteratorFor [Monad m] [Monad n] [Iterator α m β] [Finite α m] :
172172
IteratorFor (Take α m β) m n :=
173173
.defaultImplementation
174174
-- TODO: use [IteratorFor α m n]

Iterator/Combinators/Zip.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@ instance [Monad m] [Productive α₁ m] [Finite α₂ m] :
304304
instance ZipH.instIteratorToArray [Monad m] [Finite (ZipH α₁ m α₂ β₂) m] : IteratorToArray (ZipH α₁ m α₂ β₂) m :=
305305
.defaultImplementation
306306

307-
instance ZipH.instIteratorFor [Monad m] [Monad n] [MonadLiftT m n] [Finite (ZipH α₁ m α₂ β₂) m] :
307+
instance ZipH.instIteratorFor [Monad m] [Monad n] [Finite (ZipH α₁ m α₂ β₂) m] :
308308
IteratorFor (ZipH α₁ m α₂ β₂) m n :=
309309
.defaultImplementation
310310

Iterator/Consumers/Loop.lean

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,56 @@
11
import Iterator.Basic
22

33
@[specialize]
4-
def IterM.DefaultConsumers.forIn {m : Type w → Type w'} {n : Type w → Type w''} [Monad n] [MonadLiftT m n]
4+
def IterM.DefaultConsumers.forIn {m : Type w → Type w'}
5+
{n : Type w → Type w''} [Monad n] (lift : ∀ γ, m γ → n γ)
56
{α : Type w} {β : Type v} {γ : Type w}
67
[Iterator α m β] [Finite α m]
78
(it : IterM (α := α) m β) (init : γ)
8-
(f : (b : β) → (c : γ) → n (ForInStep γ)) : n γ := do
9-
match (← it.stepH).inflate with
10-
| .yield it' out _ =>
11-
match ← f out init with
12-
| .yield c => IterM.DefaultConsumers.forIn it' c f
13-
| .done c => return c
14-
| .skip it' _ => IterM.DefaultConsumers.forIn it' init f
15-
| .done _ => return init
9+
(f : (b : β) → (c : γ) → n (ForInStep γ)) : n γ :=
10+
letI : MonadLift m n := ⟨fun {γ} => lift γ⟩
11+
do
12+
match (← it.stepH).inflate with
13+
| .yield it' out _ =>
14+
match ← f out init with
15+
| .yield c => IterM.DefaultConsumers.forIn lift it' c f
16+
| .done c => return c
17+
| .skip it' _ => IterM.DefaultConsumers.forIn lift it' init f
18+
| .done _ => return init
1619
termination_by it.finitelyManySteps
1720

18-
class IteratorFor (α : Type w) (m : Type w → Type w') {β : Type v} [Iterator α m β] (n : Type w → Type w'') where
19-
forIn : ∀ {γ : Type w}, IterM (α := α) m β → γ →
20-
((b : β) → (c : γ) → n (ForInStep γ)) →
21-
n γ
21+
class IteratorFor (α : Type w) (m : Type w → Type w') {β : Type v} [Iterator α m β]
22+
(n : Type w → Type w'') where
23+
forIn : ∀ (_lift : (γ : Type w) → m γ → n γ) {γ : Type w},
24+
IterM (α := α) m β → γ →
25+
((b : β) → (c : γ) → n (ForInStep γ)) → n γ
2226

2327
class LawfulIteratorFor (α : Type w) (m : Type w → Type w') (n : Type w → Type w'')
24-
[Monad n] [Iterator α m β] [Finite α m] [IteratorFor α m n] [MonadLiftT m n] where
25-
lawful : ∀ γ, IteratorFor.forIn (α := α) (m := m) (n := n) (γ := γ) =
26-
IterM.DefaultConsumers.forIn (α := α) (m := m) (n := n) (γ := γ)
28+
[Monad n] [Iterator α m β] [Finite α m] [IteratorFor α m n] where
29+
lawful : ∀ lift γ, IteratorFor.forIn lift (α := α) (m := m) (γ := γ) =
30+
IterM.DefaultConsumers.forIn (α := α) (m := m) (n := n) (lift := lift) (γ := γ)
2731

2832
def IteratorFor.defaultImplementation {α : Type w} {m : Type w → Type w'} {n : Type w → Type w'}
29-
[Monad m] [Monad n] [MonadLiftT m n] [Iterator α m β] [Finite α m] :
33+
[Monad m] [Monad n] [Iterator α m β] [Finite α m] :
3034
IteratorFor α m n where
31-
forIn := IterM.DefaultConsumers.forIn
35+
forIn lift := IterM.DefaultConsumers.forIn lift
3236

3337
instance (α : Type w) (m : Type w → Type w') (n : Type w → Type w')
34-
[Monad m] [Monad n] [MonadLiftT m n] [Iterator α m β] [Finite α m] :
35-
haveI : IteratorFor α m n := .defaultImplementation
38+
[Monad m] [Monad n] [Iterator α m β] [Finite α m] :
39+
letI : IteratorFor α m n := .defaultImplementation
3640
LawfulIteratorFor α m n :=
3741
letI : IteratorFor α m n := .defaultImplementation
38-
fun _ => rfl⟩
42+
fun _ _ => rfl⟩
3943

4044
instance {m : Type w → Type w'} {n : Type w → Type w''}
41-
{α : Type w} {β : Type v} [Iterator α m β] [IteratorFor α m n] :
45+
{α : Type w} {β : Type v} [Iterator α m β] [IteratorFor α m n]
46+
[MonadLiftT m n] :
4247
ForIn n (IterM (α := α) m β) β where
43-
forIn := IteratorFor.forIn
48+
forIn := IteratorFor.forIn (fun _ => MonadLiftT.monadLift)
4449

4550
@[specialize]
4651
def IterM.foldM {m : Type w → Type w'} {n : Type w → Type w'} [Monad n]
4752
{α : Type w} {β : Type v} {γ : Type w} [Iterator α m β] [IteratorFor α m n]
53+
[MonadLiftT m n]
4854
(f : γ → β → n γ) (init : γ) (it : IterM (α := α) m β) : n γ :=
4955
ForIn.forIn it init (fun x acc => ForInStep.yield <$> f acc x)
5056

Iterator/Examples.lean

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,18 @@ end Primes
2222

2323
def hideEggs : IO Unit := do
2424
-- Repeat colors and locations indefinitely
25-
let colors := IterM.unfold Id (0 : Nat) (· + 1) |>.map fun n =>
25+
let colors := Iter.unfold (0 : Nat) (· + 1) |>.map fun n =>
2626
#["green", "red", "yellow"][n % 3]!
27-
let locations := IterM.unfold Id (0 : Nat) (· + 1) |>.map fun n =>
27+
let locations := Iter.unfold (0 : Nat) (· + 1) |>.map fun n =>
2828
#["in a boot", "underneath a lampshade", "under the cushion", "in the lawn"][n % 4]!
2929
-- Summon the chickens
30-
let chickens := ["Clucky", "Patches", "Fluffy"].iter Id
30+
let chickens := ["Clucky", "Patches", "Fluffy"].iter
3131
-- Gather, color and hide the eggs
32-
let eggs := chickens.flatMap (fun x : String => IterM.unfold Id x id |>.take 3)
32+
let eggs := chickens.flatMap (fun x : String => Iter.unfold x id |>.take 3)
3333
|>.zip colors
3434
|>.zip locations
3535
-- Report the results (top secret)
36-
let eggsIO := eggs.switchMonad (pure : ∀ {γ}, γ → IO γ) -- Obtain an IO-monadic iterator
37-
for x in eggsIO do
36+
for x in eggs do
3837
IO.println s! "{x.1.1} hides a {x.1.2} egg {x.2}."
3938
-- Alternative : eggsIO.mapM (fun x => IO.println s!"{x.1.1} hides a {x.1.2} egg {x.2}.") |>.drain
4039

@@ -60,7 +59,7 @@ def firstOfEach (l : List (List Nat)) : List Nat :=
6059
#eval! firstOfEach [[1, 2], [], [3, 4]]
6160

6261
def deepSum (l : List (List Nat)) : Nat :=
63-
go (l.iter Id |>.flatMap fun l' => l'.iter Id) 0
62+
go (l.iter |>.flatMap fun l' => l'.iter) 0
6463
where
6564
@[specialize]
6665
go it acc :=
@@ -107,15 +106,15 @@ Additional diagnostic information may be available using the `set_option diagnos
107106
-- as Rust
108107

109108
def dependentFlatMap (l : List (List Nat)) : List Nat :=
110-
let it := IterM.unfold Id 2 (· + 1) |>.zip l.iter
111-
it.flatMapD (fun (x : Nat × List Nat) => (x.2.iter Id).filter fun y => y % x.1 = 0) |>.toList
109+
let it := Iter.unfold 2 (· + 1) |>.zip l.iter
110+
it.flatMapD (fun (x : Nat × List Nat) => x.2.iter.filter fun y => y % x.1 = 0) |>.toList
112111

113112
/-- info: [2, 6, 9] -/
114113
#guard_msgs in
115114
#eval! dependentFlatMap [[1, 2, 3], [4, 5, 6, 9]]
116115

117116
def addIndices (l : List Nat) : List (Nat × Nat) :=
118-
IterM.unfold Id 0 (· + 1) |>.zip (l.iter Id) |>.toList
117+
Iter.unfold 0 (· + 1) |>.zip l.iter |>.toList
119118

120119
/-- info: [(0, 3), (1, 1), (2, 4), (3, 1), (4, 5), (5, 9)] -/
121120
#guard_msgs in
@@ -126,7 +125,7 @@ def addIndices (l : List Nat) : List (Nat × Nat) :=
126125
#eval! [3, 1, 4, 1, 5, 9].iter.filter (· % 2 = 0) |>.toList
127126

128127
def printNums (l : List Nat) : IO Unit :=
129-
l.iter IO |>.mapM (fun n => do IO.println (toString n); pure n) |>.drain
128+
l.iterM IO |>.mapM (fun n => do IO.println (toString n); pure n) |>.drain
130129

131130

132131
/--
@@ -139,7 +138,7 @@ info: 1
139138

140139
-- Same result as `printNums` but showcasing that we can use iterators in `for-in` constructs
141140
def printNumsForIn (l : List Nat) : IO Unit := do
142-
for n in l.iter IO do
141+
for n in l.iter do
143142
IO.println n
144143

145144
def timestamps (n : Nat) : IO (List Std.Time.PlainTime) := do
@@ -162,7 +161,7 @@ def timestamps (n : Nat) : IO (List Std.Time.PlainTime) := do
162161

163162
-- This example demonstrates that chained `mapM` calls are executed in a different order than with `List.mapM`.
164163
def chainedMapM (l : List Nat) : IO Unit :=
165-
l.iter IO |>.mapM (IO.println <| s!"1st {.}") |>.mapM (IO.println <| s!"2nd {·}") |>.drain
164+
l.iterM IO |>.mapM (IO.println <| s!"1st {.}") |>.mapM (IO.println <| s!"2nd {·}") |>.drain
166165

167166
/--
168167
info: 1st 1

Iterator/Producers.lean

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ prelude
77
import Iterator.Basic
88
import Iterator.Consumers.Collect
99
import Iterator.Consumers.Loop
10+
import Iterator.Pure.Basic
1011
import Init.Data.Nat.Lemmas
1112

1213
section ListIterator
@@ -21,10 +22,15 @@ Returns a finite iterator for the given list.
2122
The iterator yields the elements of the list in order and then terminates.
2223
-/
2324
@[always_inline, inline]
24-
def List.iter {α : Type w} (l : List α) (m : Type w → Type w' := by exact Id) [Pure m] :
25+
def List.iterM {α : Type w} (l : List α) (m : Type w → Type w') [Pure m] :
2526
IterM (α := ListIterator α) m α :=
2627
toIter { list := l } m α
2728

29+
@[always_inline, inline]
30+
def List.iter {α : Type w} (l : List α) :
31+
Iter (α := ListIterator α) α :=
32+
((l.iterM Id).toPureIter : Iter α)
33+
2834
instance {α : Type w} [Pure m] : Iterator (ListIterator α) m α where
2935
plausible_step it
3036
| .yield it' out => it.inner.list = out :: it'.inner.list
@@ -46,7 +52,7 @@ instance [Pure m] : FinitenessRelation (ListIterator α) m where
4652
instance {α : Type w} [Monad m] : IteratorToArray (ListIterator α) m :=
4753
.defaultImplementation
4854

49-
instance {α : Type w} [Monad m] [Monad n] [MonadLiftT m n] : IteratorFor (ListIterator α) m n :=
55+
instance {α : Type w} [Monad m] [Monad n] : IteratorFor (ListIterator α) m n :=
5056
.defaultImplementation
5157

5258
end ListIterator
@@ -72,10 +78,14 @@ instance [Pure m] : Iterator (UnfoldIterator α f) m α where
7278
Creates an infinite, productive iterator. First it yields `init`.
7379
If the last step yielded `a`, the next will yield `f a`.
7480
-/
75-
@[inline]
81+
@[always_inline, inline]
7682
def IterM.unfold (m : Type w → Type w') [Pure m] {α : Type w} (init : α) (f : α → α) :=
7783
toIter (UnfoldIterator.mk (f := f) init) m α
7884

85+
@[always_inline, inline]
86+
def Iter.unfold {α : Type w} (init : α) (f : α → α) :=
87+
((IterM.unfold Id init f).toPureIter : Iter α)
88+
7989
instance [Pure m] : ProductivenessRelation (UnfoldIterator α f) m where
8090
rel := emptyWf.rel
8191
wf := emptyWf.wf

0 commit comments

Comments
 (0)