Skip to content

Commit 5bce2d3

Browse files
committed
wip; need to prove slice size lawful
1 parent ded746a commit 5bce2d3

File tree

26 files changed

+745
-521
lines changed

26 files changed

+745
-521
lines changed

src/Init/Data/Iterators/Combinators/Monadic/Attach.lean

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -106,16 +106,6 @@ instance Attach.instIteratorLoopPartial {α β : Type w} {m : Type w → Type w'
106106
IteratorLoopPartial (Attach α m P) m n :=
107107
.defaultImplementation
108108

109-
instance {α β : Type w} {m : Type w → Type w'} [Monad m]
110-
{P : β → Prop} [Iterator α m β] [IteratorSize α m] :
111-
IteratorSize (Attach α m P) m where
112-
size it := IteratorSize.size it.internalState.inner
113-
114-
instance {α β : Type w} {m : Type w → Type w'} [Monad m]
115-
{P : β → Prop} [Iterator α m β] [IteratorSizePartial α m] :
116-
IteratorSizePartial (Attach α m P) m where
117-
size it := IteratorSizePartial.size it.internalState.inner
118-
119109
end Types
120110

121111
/--

src/Init/Data/Iterators/Combinators/Monadic/FilterMap.lean

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -604,30 +604,4 @@ def IterM.filter {α β : Type w} {m : Type w → Type w'} [Iterator α m β] [M
604604
(f : β → Bool) (it : IterM (α := α) m β) :=
605605
(it.filterMap (fun b => if f b then some b else none) : IterM m β)
606606

607-
instance {α β γ : Type w} {m : Type w → Type w'}
608-
[Iterator α m β] {lift : ⦃α : Type w⦄ → m α → Id α}
609-
{f : β → PostconditionT Id (Option γ)} [Finite α m] :
610-
IteratorSize (FilterMap α m Id lift f) Id :=
611-
.defaultImplementation
612-
613-
instance {α β γ : Type w} {m : Type w → Type w'}
614-
[Iterator α m β] {lift : ⦃α : Type w⦄ → m α → Id α}
615-
{f : β → PostconditionT Id (Option γ)} :
616-
IteratorSizePartial (FilterMap α m Id lift f) Id :=
617-
.defaultImplementation
618-
619-
instance {α β γ : Type w} {m : Type w → Type w'}
620-
{n : Type w → Type w''} [Monad n] [Iterator α m β]
621-
{lift : ⦃α : Type w⦄ → m α → n α}
622-
{f : β → PostconditionT n γ} [IteratorSize α m] :
623-
IteratorSize (Map α m n lift f) n where
624-
size it := IteratorSize.size it.internalState.inner
625-
626-
instance {α β γ : Type w} {m : Type w → Type w'}
627-
{n : Type w → Type w''} [Monad n] [Iterator α m β]
628-
{lift : ⦃α : Type w⦄ → m α → n α}
629-
{f : β → PostconditionT n γ} [IteratorSizePartial α m] :
630-
IteratorSizePartial (Map α m n lift f) n where
631-
size it := IteratorSizePartial.size it.internalState.inner
632-
633607
end Std.Iterators

src/Init/Data/Iterators/Combinators/Monadic/ULift.lean

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -140,16 +140,6 @@ instance Types.ULiftIterator.instIteratorCollectPartial {o} [Monad n] [Monad o]
140140
IteratorCollectPartial (ULiftIterator α m n β lift) n o :=
141141
.defaultImplementation
142142

143-
instance Types.ULiftIterator.instIteratorSize [Monad n] [Iterator α m β] [IteratorSize α m]
144-
[Finite (ULiftIterator α m n β lift) n] :
145-
IteratorSize (ULiftIterator α m n β lift) n where
146-
size it := it.internalState.inner.size
147-
148-
instance Types.ULiftIterator.instIteratorSizePartial [Monad n] [Iterator α m β]
149-
[IteratorSizePartial α m] :
150-
IteratorSizePartial (ULiftIterator α m n β lift) n where
151-
size it := it.internalState.inner.allowNontermination.size
152-
153143
/--
154144
Transforms an `m`-monadic iterator with values in `β` into an `n`-monadic iterator with
155145
values in `ULift β`. Requires a `MonadLift m (ULiftT n)` instance.

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

Lines changed: 10 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -256,42 +256,27 @@ def Iter.Partial.find? {α β : Type w} [Iterator α Id β] [IteratorLoopPartial
256256
Id.run (it.findM? (pure <| .up <| f ·))
257257

258258
/--
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-
This operation is not available for all iterators. If you get an error that `IteratorSizePartial`
263-
cannot be synthesized, consider using `count` instead. It is always available and steps through the
264-
whole iterator to compute its size.
259+
Steps through the whole iterator, counting the number of outputs emitted.
265260
266261
**Performance**:
267262
268-
Depends on the concrete type of the iterator. The default implementation, which is identical to
269-
`count`, is linear, but it is sometimes possible to provide an O(1) implementation.
263+
linear in the number of steps taken by the iterator
270264
-/
271265
@[always_inline, inline, expose]
272-
def Iter.size {α : Type w} {β : Type w} [Iterator α Id β] [IteratorSize α Id]
266+
def Iter.count {α : Type w} {β : Type w} [Iterator α Id β] [Finite α Id] [IteratorLoop α Id Id]
273267
(it : Iter (α := α) β) : Nat :=
274-
IteratorSize.size it.toIterM
268+
it.toIterM.count.run.down
275269

276270
/--
277-
Computes how many elements the iterator returns. In contrast to `count`, this function might take
278-
shortcuts instead of actually stepping through the whole iterator.
279-
280-
This operation is not available for all iterators. If you get an error that `IteratorSizePartial`
281-
cannot be synthesized, consider using `count` instead. It is always available and steps through the
282-
whole iterator to compute its size.
283-
284-
This is the partial version of `size`. It does not require a proof of finiteness and might loop
285-
forever. It is not possible to verify the behavior in Lean because it uses `partial`.
271+
Steps through the whole iterator, counting the number of outputs emitted.
286272
287273
**Performance**:
288274
289-
Depends on the concrete type of the iterator. The default implementation, which is identical to
290-
`count`, is linear, but it is sometimes possible to provide an O(1) implementation.
275+
linear in the number of steps taken by the iterator
291276
-/
292-
@[always_inline, inline]
293-
def Iter.Partial.size {α : Type w} {β : Type w} [Iterator α Id β] [IteratorSizePartial α Id]
294-
(it : Iter (α := α) β) : Nat :=
295-
IteratorSizePartial.size it.toIterM
277+
@[always_inline, inline, expose]
278+
def Iter.Partial.count {α : Type w} {β : Type w} [Iterator α Id β] [IteratorLoopPartial α Id Id]
279+
(it : Iter.Partial (α := α) β) : Nat :=
280+
it.it.toIterM.allowNontermination.count.run.down
296281

297282
end Std.Iterators

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

Lines changed: 11 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -88,52 +88,6 @@ class IteratorLoopPartial (α : Type w) (m : Type w → Type w') {β : Type w} [
8888
(it : IterM (α := α) m β) → γ →
8989
((b : β) → it.IsPlausibleIndirectOutput b → (c : γ) → n (ForInStep γ)) → n γ
9090

91-
/--
92-
`IteratorSize α m` provides an implementation of the `IterM.size` function.
93-
94-
This class is experimental and users of the iterator API should not explicitly depend on it.
95-
They can, however, assume that consumers that require an instance will work for all iterators
96-
provided by the standard library.
97-
-/
98-
class IteratorSize (α : Type w) (m : Type w → Type w') {β : Type w} [Iterator α m β] where
99-
size : IterM (α := α) m β → Nat
100-
101-
/--
102-
`IteratorSizePartial α m` provides an implementation of the `IterM.Partial.size` function that
103-
can be used as `it.allowTermination.size`.
104-
105-
This class is experimental and users of the iterator API should not explicitly depend on it.
106-
They can, however, assume that consumers that require an instance will work for all iterators
107-
provided by the standard library.
108-
-/
109-
class IteratorSizePartial (α : Type w) (m : Type w → Type w') {β : Type w} [Iterator α m β] where
110-
size : IterM (α := α) m β → Nat
111-
112-
/--
113-
`LawfulIteratorSize α m` ensures that the `size` function of an iterator is well-behaved.
114-
More concretely, it ensures that the successor's size is one less in case of an
115-
`IterStep.yield` result and equal in the case of an `IterStep.skip` result. The iterator may only
116-
finish immediately if its size is zero. All of these properties are expressed using the
117-
`IterM.IsPlausibleStep` predicate.
118-
119-
This class is experimental and users of the iterator API should not explicitly depend on it.
120-
-/
121-
class LawfulIteratorSize (α : Type w) {β : Type w} [Iterator α m β] [IteratorSize α m]
122-
[Monad m] where
123-
ex {it : IterM (α := α) m β} :
124-
∃ s : m (Shrink ({ s : IterStep (IterM (α := α) m β) β // match s with
125-
| .yield it' _ => IteratorSize.size it = IteratorSize.size it' + 1
126-
| .skip it' => IteratorSize.size it = IteratorSize.size it'
127-
| .done => IteratorSize.size it = 0 })),
128-
(Shrink.deflate <| Subtype.val <| Shrink.inflate ·) <$> s =
129-
(Shrink.deflate <| Subtype.val <| Shrink.inflate ·) <$> it.step
130-
-- size_eq_of_yield {it it' : IterM (α := α) m β} {out} :
131-
-- it.IsPlausibleStep (.yield it' out) → IteratorSize.size it = IteratorSize.size it' + 1
132-
-- size_eq_of_skip {it it' : IterM (α := α) m β} :
133-
-- it.IsPlausibleStep (.skip it') → IteratorSize.size it = IteratorSize.size it'
134-
-- size_eq_of_done {it : IterM (α := α) m β} :
135-
-- it.IsPlausibleStep .done → IteratorSize.size it = 0
136-
13791
end Typeclasses
13892

13993
/-- Internal implementation detail of the iterator library. -/
@@ -340,7 +294,7 @@ instance {m : Type w → Type w'} {n : Type w → Type w''}
340294
forM it f := forIn it PUnit.unit (fun out _ => do f out; return .yield .unit)
341295

342296
instance {m : Type w → Type w'} {n : Type w → Type w''}
343-
{α : Type w} {β : Type w} [Iterator α m β] [Finite α m] [IteratorLoopPartial α m n]
297+
{α : Type w} {β : Type w} [Iterator α m β] [IteratorLoopPartial α m n]
344298
[MonadLiftT m n] :
345299
ForM n (IterM.Partial (α := α) m β) β where
346300
forM it f := forIn it PUnit.unit (fun out _ => do f out; return .yield .unit)
@@ -658,14 +612,14 @@ def IterM.Partial.find? {α β : Type w} {m : Type w → Type w'} [Monad m] [Ite
658612
m (Option β) :=
659613
it.findM? (pure <| .up <| f ·)
660614

661-
section Size
615+
section Count
662616

663617
/--
664618
This is the implementation of the default instance `IteratorSize.defaultImplementation`.
665619
-/
666620
@[always_inline, inline]
667621
def IterM.DefaultConsumers.count {α : Type w} {m : Type w → Type w'} [Monad m] {β : Type w}
668-
[Iterator α m β] [IteratorLoop α m m] [Finite α m] (it : IterM (α := α) m β) :
622+
[Iterator α m β] [Finite α m] [IteratorLoop α m m] (it : IterM (α := α) m β) :
669623
m (ULift Nat) :=
670624
it.fold (init := .up 0) fun acc _ => .up (acc.down + 1)
671625

@@ -686,9 +640,10 @@ Steps through the whole iterator, counting the number of outputs emitted.
686640
linear in the number of steps taken by the iterator
687641
-/
688642
@[always_inline, inline]
689-
def IterM.count {α : Type} {m : TypeType w'} {β : Type} [Iterator α m β] [IteratorLoop α m m]
690-
[Monad m] [Finite α m] (it : IterM (α := α) m β) : m Nat :=
691-
ULift.down <$> IterM.DefaultConsumers.count it
643+
def IterM.count {α : Type w} {m : Type w → Type w'} {β : Type w} [Iterator α m β] [Finite α m]
644+
[IteratorLoop α m m]
645+
[Monad m] (it : IterM (α := α) m β) : m (ULift Nat) :=
646+
IterM.DefaultConsumers.count it
692647

693648
/--
694649
Steps through the whole iterator, counting the number of outputs emitted.
@@ -698,73 +653,10 @@ Steps through the whole iterator, counting the number of outputs emitted.
698653
linear in the number of steps taken by the iterator
699654
-/
700655
@[always_inline, inline]
701-
def IterM.Partial.count {α : Type} {m : TypeType w'} {β : Type} [Iterator α m β]
702-
[IteratorLoopPartial α m m] [Monad m] (it : IterM.Partial (α := α) m β)
703-
[IteratorSizePartial α m] : m Nat :=
704-
ULift.down <$> IterM.DefaultConsumers.countPartial it.it
705-
706-
set_option pp.universes true
707-
/--
708-
This is the default implementation of the `IteratorSize` class.
709-
It simply iterates using `IteratorLoop` and counts the elements.
710-
For certain iterators, more efficient implementations are possible and should be used instead.
711-
-/
712-
@[always_inline, inline]
713-
def IteratorSize.defaultImplementation {α β : Type w}
714-
[Iterator α Id β] [Finite α Id] [IteratorLoop α Id Id] :
715-
IteratorSize α Id where
716-
size it := IterM.DefaultConsumers.count it |>.run.down
717-
718-
/--
719-
This is the default implementation of the `IteratorSizePartial` class.
720-
It simply iterates using `IteratorLoopPartial` and counts the elements.
721-
For certain iterators, more efficient implementations are possible and should be used instead.
722-
-/
723-
@[always_inline, inline]
724-
instance IteratorSizePartial.defaultImplementation {α β : Type w}
725-
[Iterator α Id β] [IteratorLoopPartial α Id Id] :
726-
IteratorSizePartial α Id where
727-
size it := IterM.DefaultConsumers.countPartial it |>.run.down
728-
729-
/--
730-
Computes how many elements the iterator returns. In contrast to `count`, this function might take
731-
shortcuts instead of actually stepping through the whole iterator and it has no monadic side effects.
732-
733-
This operation is not available for all iterators. If you get an error that `IteratorSize` cannot
734-
be synthesized, consider using `count` instead. It is always available and steps through the whole
735-
iterator to compute its size.
736-
737-
**Performance**:
738-
739-
Depends on the concrete type of the iterator. The default implementation, which is identical to
740-
`count`, is linear, but it is sometimes possible to provide an O(1) implementation.
741-
-/
742-
@[always_inline, inline]
743-
def IterM.size {α : Type w} {β : Type w} [Iterator α m β] [IteratorSize α m]
744-
(it : IterM (α := α) m β) : Nat :=
745-
IteratorSize.size it
746-
747-
/--
748-
Computes how many elements the iterator returns. In contrast to `count`, this function might take
749-
shortcuts instead of actually stepping through the whole iterator.
750-
751-
This operation is not available for all iterators. If you get an error that `IteratorSizePartial`
752-
cannot be synthesized, consider using `count` instead. It is always available and steps through the
753-
whole iterator to compute its size.
754-
755-
This is the partial version of `size`. It does not require a proof of finiteness and might loop
756-
forever. It is not possible to verify the behavior in Lean because it uses `partial`.
757-
758-
**Performance**:
759-
760-
Depends on the concrete type of the iterator. The default implementation, which is identical to
761-
`count`, is linear, but it is sometimes possible to provide an O(1) implementation.
762-
-/
763-
@[always_inline, inline]
764-
def IterM.Partial.size {α : Type w} {β : Type w} [Iterator α m β]
765-
(it : IterM.Partial (α := α) m β) [IteratorSizePartial α m] : Nat :=
766-
IteratorSizePartial.size it.it
656+
def IterM.Partial.count {α : Type w} {m : Type w → Type w'} {β : Type w} [Iterator α m β]
657+
[IteratorLoopPartial α m m] [Monad m] (it : IterM.Partial (α := α) m β) : m (ULift Nat) :=
658+
IterM.DefaultConsumers.countPartial it.it
767659

768-
end Size
660+
end Count
769661

770662
end Std.Iterators

0 commit comments

Comments
 (0)