Skip to content

Commit 96b81f3

Browse files
authored
feat: lemmas about list iterators (#8384)
This PR provides lemmas about the behavior of `step`, `toArray`, `toList` and `toListRev` on list iterators created with `List.iter` and `List.iterM`.
1 parent 44ff700 commit 96b81f3

File tree

7 files changed

+149
-2
lines changed

7 files changed

+149
-2
lines changed

src/Std/Data/Iterators/Basic.lean

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,21 @@ def IterStep.mapIterator {α' : Type u'} (f : α → α') : IterStep α β → I
183183
| .skip it => .skip (f it)
184184
| .done => .done
185185

186+
@[simp]
187+
theorem IterStep.mapIterator_yield {α' : Type u'} {f : α → α'} {it : α} {out : β} :
188+
(IterStep.yield it out).mapIterator f = IterStep.yield (f it) out :=
189+
rfl
190+
191+
@[simp]
192+
theorem IterStep.mapIterator_skip {α' : Type u'} {f : α → α'} {it : α} :
193+
(IterStep.skip it (β := β)).mapIterator f = IterStep.skip (f it) :=
194+
rfl
195+
196+
@[simp]
197+
theorem IterStep.mapIterator_done {α' : Type u'} {f : α → α'} :
198+
(IterStep.done (α := α) (β := β)).mapIterator f = IterStep.done :=
199+
rfl
200+
186201
@[simp]
187202
theorem IterStep.mapIterator_mapIterator {α' : Type u'} {α'' : Type u''}
188203
{f : α → α'} {g : α' → α''} {step : IterStep α β} :

src/Std/Data/Iterators/Consumers/Monadic/Collect.lean

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ They can, however, assume that consumers that require an instance will work for
3535
provided by the standard library.
3636
-/
3737
class IteratorCollect (α : Type w) (m : Type w → Type w') {β : Type w} [Iterator α m β] where
38+
/--
39+
Maps the emitted values of an iterator using the given function and collects the results in an
40+
`Array`. This is an internal implementation detail. Consider using `it.map f |>.toArray` instead.
41+
-/
3842
toArrayMapped [Finite α m] : ∀ {γ : Type w}, (β → m γ) → IterM (α := α) m β → m (Array γ)
3943

4044
/--
@@ -46,8 +50,13 @@ They can, however, assume that consumers that require an instance will work for
4650
provided by the standard library.
4751
-/
4852
class IteratorCollectPartial
49-
(α : Type w) (m : Type w → Type w') {β : Type w} [Iterator α m β] where
50-
toArrayMappedPartial : ∀ {γ : Type w}, (β → m γ) → IterM (α := α) m β → m (Array γ)
53+
(α : Type w) (m : Type w → Type w') {β : Type w} [Iterator α m β] where
54+
/--
55+
Maps the emitted values of an iterator using the given function and collects the results in an
56+
`Array`. This is an internal implementation detail.
57+
Consider using `it.map f |>.allowNontermination.toArray` instead.
58+
-/
59+
toArrayMappedPartial : ∀ {γ : Type w}, (β → m γ) → IterM (α := α) m β → m (Array γ)
5160

5261
end Typeclasses
5362

src/Std/Data/Iterators/Lemmas.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ prelude
77
import Std.Data.Iterators.Lemmas.Basic
88
import Std.Data.Iterators.Lemmas.Monadic
99
import Std.Data.Iterators.Lemmas.Consumers
10+
import Std.Data.Iterators.Lemmas.Producers
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
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.Lemmas.Producers.Monadic
8+
import Std.Data.Iterators.Lemmas.Producers.List
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
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.Consumers
8+
import Std.Data.Iterators.Lemmas.Consumers.Collect
9+
import Std.Data.Iterators.Lemmas.Producers.Monadic.List
10+
11+
/-!
12+
# Lemmas about list iterators
13+
14+
This module provides lemmas about the interactions of `List.iter` with `Iter.step` and various
15+
collectors.
16+
-/
17+
18+
namespace Std.Iterators
19+
20+
variable {β : Type w}
21+
22+
@[simp]
23+
theorem _root_.List.step_iter_nil :
24+
(([] : List β).iter).step = ⟨.done, rfl⟩ := by
25+
simp only [Iter.step, IterM.step, Iterator.step]; rfl
26+
27+
@[simp]
28+
theorem _root_.List.step_iter_cons {x : β} {xs : List β} :
29+
((x :: xs).iter).step = ⟨.yield xs.iter x, rfl⟩ := by
30+
simp only [List.iter, List.iterM, IterM.step, Iterator.step]; rfl
31+
32+
@[simp]
33+
theorem _root_.List.toArray_iter {m : Type w → Type w'} [Monad m] [LawfulMonad m] {l : List β} :
34+
l.iter.toArray = l.toArray := by
35+
simp [List.iter, List.toArray_iterM, Iter.toArray_eq_toArray_toIterM]
36+
37+
@[simp]
38+
theorem _root_.List.toList_iter {m : Type w → Type w'} [Monad m] [LawfulMonad m] {l : List β} :
39+
l.iter.toList = l := by
40+
simp [List.iter, List.toList_iterM]
41+
42+
@[simp]
43+
theorem _root_.List.toListRev_iter {m : Type w → Type w'} [Monad m] [LawfulMonad m] {l : List β} :
44+
l.iter.toListRev = l.reverse := by
45+
simp [List.iter, Iter.toListRev_eq_toListRev_toIterM, List.toListRev_iterM]
46+
47+
end Std.Iterators
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
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.Lemmas.Producers.Monadic.List
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
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.Producers.Monadic.List
8+
import Std.Data.Iterators.Consumers
9+
import Std.Data.Iterators.Lemmas.Consumers.Monadic
10+
11+
/-!
12+
# Lemmas about list iterators
13+
14+
This module provides lemmas about the interactions of `List.iterM` with `IterM.step` and various
15+
collectors.
16+
-/
17+
18+
namespace Std.Iterators
19+
20+
variable {m : Type w → Type w'} [Monad m] {β : Type w}
21+
22+
@[simp]
23+
theorem _root_.List.step_iterM_nil :
24+
(([] : List β).iterM m).step = pure ⟨.done, rfl⟩ := by
25+
simp only [IterM.step, Iterator.step]; rfl
26+
27+
@[simp]
28+
theorem _root_.List.step_iterM_cons {x : β} {xs : List β} :
29+
((x :: xs).iterM m).step = pure ⟨.yield (xs.iterM m) x, rfl⟩ := by
30+
simp only [List.iterM, IterM.step, Iterator.step]; rfl
31+
32+
theorem ListIterator.toArrayMapped_toIterM [LawfulMonad m]
33+
{β : Type w} {γ : Type w} {f : β → m γ} {l : List β} :
34+
IteratorCollect.toArrayMapped f (l.iterM m) = List.toArray <$> l.mapM f := by
35+
rw [LawfulIteratorCollect.toArrayMapped_eq]
36+
induction l with
37+
| nil =>
38+
rw [IterM.DefaultConsumers.toArrayMapped_eq_match_step]
39+
simp [List.step_iterM_nil]
40+
| cons x xs ih =>
41+
rw [IterM.DefaultConsumers.toArrayMapped_eq_match_step]
42+
simp [List.step_iterM_cons, List.mapM_cons, pure_bind, ih]
43+
44+
@[simp]
45+
theorem _root_.List.toArray_iterM [LawfulMonad m] {l : List β} :
46+
(l.iterM m).toArray = pure l.toArray := by
47+
simp only [IterM.toArray, ListIterator.toArrayMapped_toIterM]
48+
rw [List.mapM_pure, map_pure, List.map_id']
49+
50+
@[simp]
51+
theorem _root_.List.toList_iterM [LawfulMonad m] {l : List β} :
52+
(l.iterM m).toList = pure l := by
53+
rw [← IterM.toList_toArray, List.toArray_iterM, map_pure, List.toList_toArray]
54+
55+
@[simp]
56+
theorem _root_.List.toListRev_iterM [LawfulMonad m] {l : List β} :
57+
(l.iterM m).toListRev = pure l.reverse := by
58+
simp [IterM.toListRev_eq, List.toList_iterM]
59+
60+
end Std.Iterators

0 commit comments

Comments
 (0)