You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -257,16 +257,20 @@ Thus, Lean divides iterators into three termination classes:
257
257
All finite iterators are necessarily productive.
258
258
:::
259
259
260
-
{docstring Finite +allowMissing}
260
+
{docstring Finite}
261
261
262
-
{docstring Productive +allowMissing}
262
+
{docstring Productive}
263
263
264
-
Sometimes, a needed {name}`Finite`instanceisnotavailablebecauseaniteratorhasnotyetbeenprovedfinite.
265
-
Inthesecases, {name}`Iter.allowNontermination` can be used to bypass a finiteness requirement.
264
+
Lean's standard library provides many functions that iterate over an iterator. These consumer functions usually do not
265
+
make any assumptions about the underlying iterator. In particular, such functions may run forever for certain iterators.
266
266
267
-
{docstring Iter.allowNontermination}
267
+
Sometimes, it is of utmost importance that a function does terminate.
268
+
For these cases, the combinator {name}`Iter.ensureTermination` results in an iterator that provides variants of consumers that are guaranteed to terminate.
269
+
They usually require proof that the involved iterator is finite.
268
270
269
-
{docstring IterM.allowNontermination}
271
+
{docstring Iter.ensureTermination}
272
+
273
+
{docstring IterM.ensureTermination}
270
274
271
275
::::example"Iterating Over `Nat`"
272
276
```imports -show
@@ -300,6 +304,18 @@ instance [Pure m] : Iterator Nats m Nat where
300
304
pure <| .deflate <|
301
305
.yield { it with internalState.next := n + 1 } n (by grind)
302
306
```
307
+
308
+
Whenever an iterator is defined, {name}`IteratorCollect` and {name}`IteratorLoop` instances should be provided.
309
+
They are required for most consumers of iterators such as {name}`Iter.toList` or the `for` loops.
310
+
One can use their default implementations as follows:
311
+
312
+
```lean
313
+
instance [Pure m] [Monad n] : IteratorCollect Nats m n :=
314
+
.defaultImplementation
315
+
316
+
instance [Pure m] [Monad n] : IteratorLoop Nats m n :=
Hint: Typeclassinstanceresolutionfailurescanbeinspectedwith the `set_option trace.Meta.synthInstance true` command.
447
511
```
448
512
449
-
To prove finiteness, it's easiest to start at {name}`TriplePos.done` and work backwards toward {name}`TriplePos.fst`, showing that each position in turn has a finite chain of successors:
513
+
To support {name}`Iter.toArray`, the default implementation of {name}`IteratorCollect` can be used:
514
+
515
+
```lean
516
+
instance [Iterator (TripleIterator α) m α] [Monad n] :
517
+
IteratorCollect (TripleIterator α) m n :=
518
+
IteratorCollect.defaultImplementation
519
+
```
520
+
521
+
With the {name}`IteratorCollect`instanceinplace, {name}`Iter.toArray` now works:
522
+
```lean (name := abcToArray)
523
+
#eval abc.iter.toArray
524
+
```
525
+
```leanOutput abcToArray
526
+
#['a', 'b', 'c']
527
+
```
528
+
529
+
In general, `Iter.toArray` might run forever. One can prove that `abc` is finite, and the above example will terminate after finitely many steps, by
530
+
constructing a `Finite (Triple Char) Id` instance.
531
+
It's easiest to start at {name}`TriplePos.done` and work backwards toward {name}`TriplePos.fst`, showing that each position in turn has a finite chain of successors:
450
532
451
533
```lean
452
534
@[grind! .]
@@ -487,28 +569,8 @@ instance [Pure m] : Finite (TripleIterator α) m where
487
569
cases pos <;> grind
488
570
```
489
571
490
-
With the {name}`Finite`instanceinplace,thedefaultimplementationof {name}`IteratorCollect` can be used:
491
-
492
-
```lean
493
-
instance [Iterator (TripleIterator α) m α] [Monad n] :
494
-
IteratorCollect (TripleIterator α) m n :=
495
-
IteratorCollect.defaultImplementation
496
-
```
497
-
498
-
{name}`Iter.toArray` now works:
499
-
```lean (name := abcToArray)
500
-
#eval abc.iter.toArray
501
-
```
502
-
```leanOutput abcToArray
503
-
#['a', 'b', 'c']
504
-
```
505
-
506
-
To enable the iterator in {keywordOf Lean.Parser.Term.doFor}`for` loops, instances of {name}`IteratorLoopPartial` and {name}`IteratorLoop` are needed:
572
+
To enable the iterator in {keywordOf Lean.Parser.Term.doFor}`for` loops, an instanceof {name}`IteratorLoop` are needed:
To make the {tech}[universe levels] of iterators more flexible, a wrapper type {name Std.Shrink}`Shrink` is applied around the result of {name}`Iterator.step`.
@@ -655,7 +709,7 @@ There are three primary ways to consume an iterator:
655
709
: {keywordOf Lean.Parser.Term.doFor}`for` loops
656
710
657
711
A {keywordOf Lean.Parser.Term.doFor}`for` loop can consume an iterator, making each value available in its body.
658
-
This requires that the iterator haveeither an instanceof {name}`IteratorLoop` or {name}`IteratorLoopPartial`for the loop's monad.
712
+
This requires that the iterator have an instanceof {name}`IteratorLoop`for the loop's monad.
659
713
660
714
: Stepping through iterators
661
715
@@ -701,25 +755,26 @@ import Std.Data.Iterators
701
755
```lean -show
702
756
open Std.Iterators
703
757
```
704
-
Attempting to construct a list of all the natural numbers from an iterator fails:
705
-
```lean (name := toListInf) +error -keep
758
+
Attempting to construct a list of all the natural numbers from an iterator will produce an endless loop:
759
+
```lean (name := toListInf) -keep
706
760
defallNats : List Nat :=
707
761
let steps : Iter Nat := (0...*).iter
708
762
steps.toList
709
763
```
764
+
The combinator {lean}`Iter.ensureTermination` results in an iterator where non-termination is ruled out.
765
+
These iterators are guaranteed to terminate after finitely many steps, and thus cannot be used when Lean cannot prove the iterator finite.
766
+
```lean (name := toListInf) +error -keep
767
+
defallNats : List Nat :=
768
+
let steps := (0...*).iter.ensureTermination
769
+
steps.toList
770
+
```
710
771
The resulting error message states that there is no {name}`Finite`instance:
711
772
```leanOutput toListInf
712
773
failed to synthesize instanceoftypeclass
713
774
Finite (Std.Rxi.Iterator Nat) Id
714
775
715
776
Hint: Typeclassinstanceresolutionfailurescanbeinspectedwith the `set_option trace.Meta.synthInstance true` command.
716
777
```
717
-
If the failure to synthesize the instanceisduetoamissingproof,orifaninfiniteloopisdesirableforanapplication,thenthefactthatconsumingtheiteratormaynotterminatecanbehiddenusing {name}`Iter.allowNontermination`:
0 commit comments