Skip to content

Commit 18a15b8

Browse files
committed
wip
1 parent efbbb0b commit 18a15b8

File tree

3 files changed

+73
-33
lines changed

3 files changed

+73
-33
lines changed

src/Init/Data/Iterators/Consumers/Loop.lean

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -255,12 +255,33 @@ def Iter.Partial.find? {α β : Type w} [Iterator α Id β] [IteratorLoopPartial
255255
(it : Iter.Partial (α := α) β) (f : β → Bool) : Option β :=
256256
Id.run (it.findM? (pure <| .up <| f ·))
257257

258-
@[always_inline, inline, expose, inherit_doc IterM.size]
258+
/--
259+
Computes how many elements the iterator returns. In contrast to `count`, this function might take
260+
shortcuts instead of actually stepping through the whole iterator.
261+
262+
**Performance**:
263+
264+
Depends on the concrete type of the iterator. The default implementation, which is identical to
265+
`count`, is linear, but it is sometimes possible to provide an O(1) implementation.
266+
-/
267+
@[always_inline, inline, expose]
259268
def Iter.size {α : Type w} {β : Type w} [Iterator α Id β] [IteratorSize α Id]
260269
(it : Iter (α := α) β) : Nat :=
261270
(IteratorSize.size it.toIterM).run.down
262271

263-
@[always_inline, inline, inherit_doc IterM.Partial.size]
272+
/--
273+
Computes how many elements the iterator returns. In contrast to `count`, this function might take
274+
shortcuts instead of actually stepping through the whole iterator.
275+
276+
This is the partial version of `size`. It does not require a proof of finiteness and might loop
277+
forever. It is not possible to verify the behavior in Lean because it uses `partial`.
278+
279+
**Performance**:
280+
281+
Depends on the concrete type of the iterator. The default implementation, which is identical to
282+
`count`, is linear, but it is sometimes possible to provide an O(1) implementation.
283+
-/
284+
@[always_inline, inline]
264285
def Iter.Partial.size {α : Type w} {β : Type w} [Iterator α Id β] [IteratorSizePartial α Id]
265286
(it : Iter (α := α) β) : Nat :=
266287
(IteratorSizePartial.size it.toIterM).run.down

src/Init/Data/Iterators/Consumers/Monadic/Loop.lean

Lines changed: 46 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -639,7 +639,7 @@ section Size
639639
This is the implementation of the default instance `IteratorSize.defaultImplementation`.
640640
-/
641641
@[always_inline, inline]
642-
def IterM.DefaultConsumers.size {α : Type w} {m : Type w → Type w'} [Monad m] {β : Type w}
642+
def IterM.DefaultConsumers.count {α : Type w} {m : Type w → Type w'} [Monad m] {β : Type w}
643643
[Iterator α m β] [IteratorLoop α m m] [Finite α m] (it : IterM (α := α) m β) :
644644
m (ULift Nat) :=
645645
it.fold (init := .up 0) fun acc _ => .up (acc.down + 1)
@@ -648,70 +648,89 @@ def IterM.DefaultConsumers.size {α : Type w} {m : Type w → Type w'} [Monad m]
648648
This is the implementation of the default instance `IteratorSizePartial.defaultImplementation`.
649649
-/
650650
@[always_inline, inline]
651-
def IterM.DefaultConsumers.sizePartial {α : Type w} {m : Type w → Type w'} [Monad m] {β : Type w}
651+
def IterM.DefaultConsumers.countPartial {α : Type w} {m : Type w → Type w'} [Monad m] {β : Type w}
652652
[Iterator α m β] [IteratorLoopPartial α m m] (it : IterM (α := α) m β) :
653653
m (ULift Nat) :=
654654
it.allowNontermination.fold (init := .up 0) fun acc _ => .up (acc.down + 1)
655655

656+
/--
657+
Steps through the whole iterator, counting the number of outputs emitted.
658+
659+
**Performance**:
660+
661+
linear in the number of steps taken by the iterator
662+
-/
663+
@[always_inline, inline]
664+
def IterM.count {α : Type} {m : TypeType w'} {β : Type} [Iterator α m β] [IteratorLoop α m m]
665+
[Monad m] [Finite α m] (it : IterM (α := α) m β) : m Nat :=
666+
ULift.down <$> IterM.DefaultConsumers.count it
667+
668+
/--
669+
Steps through the whole iterator, counting the number of outputs emitted.
670+
671+
**Performance**:
672+
673+
linear in the number of steps taken by the iterator
674+
-/
675+
@[always_inline, inline]
676+
def IterM.Partial.count {α : Type} {m : TypeType w'} {β : Type} [Iterator α m β]
677+
[IteratorLoopPartial α m m] [Monad m] (it : IterM.Partial (α := α) m β)
678+
[IteratorSizePartial α m] : m Nat :=
679+
ULift.down <$> IterM.DefaultConsumers.countPartial it.it
680+
681+
set_option pp.universes true
656682
/--
657683
This is the default implementation of the `IteratorSize` class.
658684
It simply iterates using `IteratorLoop` and counts the elements.
659685
For certain iterators, more efficient implementations are possible and should be used instead.
660686
-/
661687
@[always_inline, inline]
662-
def IteratorSize.defaultImplementation {α β : Type w} {m : Type w → Type w'} [Monad m]
688+
def IteratorSize.defaultImplementation {α β : Type w} [Monad m]
663689
[Iterator α m β] [Finite α m] [IteratorLoop α m m] :
664690
IteratorSize α m where
665-
size := IterM.DefaultConsumers.size
666-
691+
size := IterM.DefaultConsumers.count
667692

668693
/--
669694
This is the default implementation of the `IteratorSizePartial` class.
670695
It simply iterates using `IteratorLoopPartial` and counts the elements.
671696
For certain iterators, more efficient implementations are possible and should be used instead.
672697
-/
673698
@[always_inline, inline]
674-
instance IteratorSizePartial.defaultImplementation {α β : Type w} {m : Type w → Type w'} [Monad m]
699+
instance IteratorSizePartial.defaultImplementation {α β : Type w} [Monad m]
675700
[Iterator α m β] [IteratorLoopPartial α m m] :
676701
IteratorSizePartial α m where
677-
size := IterM.DefaultConsumers.sizePartial
702+
size := IterM.DefaultConsumers.countPartial
678703

679704
/--
680-
Computes how many elements the iterator returns. In monadic situations, it is unclear which effects
681-
are caused by calling `size`, and if the monad is nondeterministic, it is also unclear what the
682-
returned value should be. The reference implementation, `IteratorSize.defaultImplementation`,
683-
simply iterates over the whole iterator monadically, counting the number of emitted values.
684-
An `IteratorSize` instance is considered lawful if it is equal to the reference implementation.
705+
Computes how many elements the iterator returns. In contrast to `count`, this function might take
706+
shortcuts instead of actually stepping through the whole iterator.
685707
686708
**Performance**:
687709
688-
Default performance is linear in the number of steps taken by the iterator.
710+
Depends on the concrete type of the iterator. The default implementation, which is identical to
711+
`count`, is linear, but it is sometimes possible to provide an O(1) implementation.
689712
-/
690713
@[always_inline, inline]
691-
def IterM.size {α : Type} {m : TypeType w'} {β : Type} [Iterator α m β] [Monad m]
692-
(it : IterM (α := α) m β) [IteratorSize α m] : m Nat :=
693-
ULift.down <$> IteratorSize.size it
714+
def IterM.size {α : Type} {β : Type} [Iterator α Id β]
715+
(it : IterM (α := α) Id β) [IteratorSize α Id] : Nat :=
716+
(IteratorSize.size it).run.down
694717

695718
/--
696-
Computes how many elements the iterator emits.
697-
698-
With monadic iterators (`IterM`), it is unclear which effects
699-
are caused by calling `size`, and if the monad is nondeterministic, it is also unclear what the
700-
returned value should be. The reference implementation, `IteratorSize.defaultImplementation`,
701-
simply iterates over the whole iterator monadically, counting the number of emitted values.
702-
An `IteratorSize` instance is considered lawful if it is equal to the reference implementation.
719+
Computes how many elements the iterator returns. In contrast to `count`, this function might take
720+
shortcuts instead of actually stepping through the whole iterator.
703721
704722
This is the partial version of `size`. It does not require a proof of finiteness and might loop
705723
forever. It is not possible to verify the behavior in Lean because it uses `partial`.
706724
707725
**Performance**:
708726
709-
Default performance is linear in the number of steps taken by the iterator.
727+
Depends on the concrete type of the iterator. The default implementation, which is identical to
728+
`count`, is linear, but it is sometimes possible to provide an O(1) implementation.
710729
-/
711730
@[always_inline, inline]
712-
def IterM.Partial.size {α : Type} {m : TypeType w'} {β : Type} [Iterator α m β] [Monad m]
713-
(it : IterM.Partial (α := α) m β) [IteratorSizePartial α m] : m Nat :=
714-
ULift.down <$> IteratorSizePartial.size it.it
731+
def IterM.Partial.size {α : Type} {β : Type} [Iterator α Id β]
732+
(it : IterM.Partial (α := α) Id β) [IteratorSizePartial α Id] : Nat :=
733+
(IteratorSizePartial.size it.it).run.down
715734

716735
end Size
717736

src/Std/Data/Iterators/Combinators/Monadic/StepSize.lean

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -154,12 +154,12 @@ instance Types.StepSizeIterator.instIteratorLoopPartial {m n} [Iterator α m β]
154154
IteratorLoopPartial (Types.StepSizeIterator α m β) m n :=
155155
.defaultImplementation
156156

157-
instance Types.StepSizeIterator.instIteratorSize {m} [Iterator α m β]
158-
[IteratorAccess α m] [Monad m] [Finite (Types.StepSizeIterator α m β) m] :
159-
IteratorSize (Types.StepSizeIterator α m β) m :=
157+
instance Types.StepSizeIterator.instIteratorSize [Iterator α Id β]
158+
[IteratorAccess α Id] [Monad Id] [Finite (Types.StepSizeIterator α Id β) Id] :
159+
IteratorSize (Types.StepSizeIterator α Id β) Id :=
160160
.defaultImplementation
161161

162-
instance Types.StepSizeIterator.instIteratorSizePartial {m} [Iterator α m β]
162+
instance Types.StepSizeIterator.instIteratorSizePartial [Iterator α m β]
163163
[IteratorAccess α m] [Monad m] :
164164
IteratorSizePartial (Types.StepSizeIterator α m β) m :=
165165
.defaultImplementation

0 commit comments

Comments
 (0)