Induction principle for productive iterators: One can define a function f that maps every
iterator it to an element of motiveit by defining fit in terms of the values of f on
the plausible skip successors of `it'.
Induction principle for productive monadic iterators: One can define a function f that maps every
iterator it to an element of motiveit by defining fit in terms of the values of f on
the plausible skip successors of `it'.
Induction principle for finite iterators: One can define a function f that maps every
iterator it to an element of motiveit by defining fit in terms of the values of f on
the plausible successors of `it'.
Induction principle for finite monadic iterators: One can define a function f that maps every
iterator it to an element of motiveit by defining fit in terms of the values of f on
the plausible successors of `it'.
PostconditionTmα represents an operation in the monad m together with a
intrinsic proof that some postcondition holds for the α valued monadic result.
It consists of a predicate P about α and an element of m({a//Pa}) and is a helpful tool
for intrinsic verification, notably termination proofs, in the context of iterators.
PostconditionTm is a monad if m is. However, note that PostconditionTmα is a structure,
so that the compiler will generate inefficient code from recursive functions returning
PostconditionTmα. Optimizations for ReaderT, StateT etc. aren't applicable for structures.
If m is a monad, then HetTm is a monad that has two features:
It generalizes m to arbitrary universes.
It tracks a postcondition property that holds for the monadic return value, similarly to
PostconditionT.
This monad is noncomputable and is merely a vehicle for more convenient proofs, especially proofs
about the equivalence of iterators, because it avoids universe issues and spares users the work
to handle the postconditions manually.
Caution: Just like PostconditionT, this is not a lawful monad transformer.
To lift from m to HetTm, use HetT.lift.
Because this monad is fundamentally universe-polymorphic, it is recommended for consistency to
always use the methods HetT.pure, HetT.map and HetT.bind instead of the homogeneous versions
Pure.pure, Functor.map and Bind.bind.
The actual monadic operation. Its return value is bundled together with a proof that
it satisfies Property and squashed so that it fits into the monad m.
A noncomputable variant of IterM.step using the HetT monad.
It is used in the definition of the equivalence relations on iterators,
namely IterM.Equiv and Iter.Equiv.
Applies the given function to the result of the contained m-monadic operation with a
proof that the postcondition property holds, returning another operation in m.
Equivalence relation on iterators. Equivalent iterators behave the same as long as the
internal state of them is not directly inspected.
Two iterators (possibly of different types) are equivalent if they have the same
Iterator.IsPlausibleStep relation and their step functions are the same up to equivalence of the
successor iterators. This coinductive definition captures the idea that the only relevant feature
of an iterator is its step function. Other information retrievable from the iterator -- for example,
whether it is a list iterator or an array iterator -- is totally irrelevant for the equivalence
judgement.
Equivalence relation on monadic iterators. Equivalent iterators behave the same as long as the
internal state of them is not directly inspected.
Two iterators (possibly of different types) are equivalent if they have the same
Iterator.IsPlausibleStep relation and their step functions are the same up to equivalence of the
successor iterators. This coinductive definition captures the idea that the only relevant feature
of an iterator is its step function. Other information retrievable from the iterator -- for example,
whether it is a list iterator or an array iterator -- is totally irrelevant for the equivalence
judgement.