seq α
is the type of possibly infinite lists (referred here as sequences).
It is encoded as an infinite stream of options such that if f n = none
, then
f m = none
for all m ≥ n
.
Equations
- stream.seq α = {f // f.is_seq}
seq1 α
is the type of nonempty sequences.
Equations
- stream.seq1 α = (α × stream.seq α)
Instances for stream.seq1
The empty sequence
Equations
Equations
Prepend an element to a sequence
Equations
- stream.seq.cons a s = ⟨option.some a::s.val, _⟩
Get the nth element of a sequence (if it exists)
Equations
A sequence has terminated at position n
if the value at position n
equals none
.
Equations
- s.terminated_at n = (s.nth n = option.none)
Instances for stream.seq.terminated_at
It is decidable whether a sequence terminates at a given position.
Equations
- s.terminated_at_decidable n = decidable_of_iff' ↥((s.nth n).is_none) _
A sequence terminates if there is some position n
at which it has terminated.
Equations
- s.terminates = ∃ (n : ℕ), s.terminated_at n
Functorial action of the functor option (α × _)
Equations
- stream.seq.omap f (option.some (a, b)) = option.some (a, f b)
- stream.seq.omap f option.none = option.none
Get the first element of a sequence
Get the tail of a sequence (or nil
if the sequence is nil
)
Equations
If a sequence terminated at position n
, it also terminated at m ≥ n
.
If s.nth n = some aₙ
for some value aₙ
, then there is also some value aₘ
such
that s.nth = some aₘ
for m ≤ n
.
Destructor for a sequence, resulting in either none
(for nil
) or
some (a, s)
(for cons a s
).
Recursion principle for sequences, compare with list.rec_on
.
Equations
- s.rec_on h1 h2 = (λ (_x : option (stream.seq1 α)) (H : s.destruct = _x), option.rec (λ (H : s.destruct = option.none), _.mpr h1) (λ (v : stream.seq1 α) (H : s.destruct = option.some v), prod.cases_on v (λ (a : α) (s' : stream.seq α) (H : s.destruct = option.some (a, s')), _.mpr (h2 a s')) H) _x H) s.destruct _
Corecursor over pairs of option
values
Equations
- stream.seq.corec.F f (option.some b) = stream.seq.corec.F._match_1 (f b)
- stream.seq.corec.F f option.none = (option.none α, option.none β)
- stream.seq.corec.F._match_1 (option.some (a, b')) = (option.some a, option.some b')
- stream.seq.corec.F._match_1 option.none = (option.none α, option.none β)
Corecursor for seq α
as a coinductive type. Iterates f
to produce new elements
of the sequence until none
is obtained.
Equations
- stream.seq.corec f b = ⟨stream.corec' (stream.seq.corec.F f) (option.some b), _⟩
Bisimilarity relation over option
of seq1 α
Equations
- stream.seq.bisim_o R (option.some (a, s)) (option.some (a', s')) = (a = a' ∧ R s s')
- stream.seq.bisim_o R (option.some (fst, snd)) option.none = false
- stream.seq.bisim_o R option.none (option.some val) = false
- stream.seq.bisim_o R option.none option.none = true
a relation is bisimiar if it meets the bisim_o
test
Equations
- stream.seq.is_bisimulation R = ∀ ⦃s₁ s₂ : stream.seq α⦄, R s₁ s₂ → stream.seq.bisim_o R s₁.destruct s₂.destruct
Embed a list as a sequence
Equations
- stream.seq.of_list l = ⟨l.nth, _⟩
Equations
Embed an infinite stream as a sequence
Equations
- stream.seq.of_stream s = ⟨stream.map option.some s, _⟩
Equations
Embed a lazy_list α
as a sequence. Note that even though this
is non-meta, it will produce infinite sequences if used with
cyclic lazy_list
s created by meta constructions.
Equations
- stream.seq.of_lazy_list = stream.seq.corec (λ (l : lazy_list α), stream.seq.of_lazy_list._match_1 l)
- stream.seq.of_lazy_list._match_1 (lazy_list.cons a l') = option.some (a, l' unit.star())
- stream.seq.of_lazy_list._match_1 lazy_list.nil = option.none
Equations
The sequence of natural numbers some 0, some 1, ...
Equations
Append two sequences. If s₁
is infinite, then s₁ ++ s₂ = s₁
,
otherwise it puts s₂
at the location of the nil
in s₁
.
Equations
- s₁.append s₂ = stream.seq.corec (λ (_x : stream.seq α × stream.seq α), stream.seq.append._match_2 _x) (s₁, s₂)
- stream.seq.append._match_2 (s₁, s₂) = stream.seq.append._match_1 s₂ s₁.destruct
- stream.seq.append._match_1 s₂ (option.some (a, s₁')) = option.some (a, s₁', s₂)
- stream.seq.append._match_1 s₂ option.none = stream.seq.omap (λ (s₂ : stream.seq α), (stream.seq.nil α, s₂)) s₂.destruct
Map a function over a sequence.
Equations
- stream.seq.map f ⟨s, al⟩ = ⟨stream.map (option.map f) s, _⟩
Flatten a sequence of sequences. (It is required that the
sequences be nonempty to ensure productivity; in the case
of an infinite sequence of nil
, the first element is never
generated.)
Equations
- stream.seq.join = stream.seq.corec (λ (S : stream.seq (stream.seq1 α)), stream.seq.join._match_1 S.destruct)
- stream.seq.join._match_1 (option.some ((a, s), S')) = option.some (a, stream.seq.join._match_2 S' s.destruct)
- stream.seq.join._match_1 option.none = option.none
- stream.seq.join._match_2 S' (option.some s') = stream.seq.cons s' S'
- stream.seq.join._match_2 S' option.none = S'
Remove the first n
elements from the sequence.
Take the first n
elements of the sequence (producing a list)
Equations
- stream.seq.take (n + 1) s = stream.seq.take._match_1 (λ (r : stream.seq α), stream.seq.take n r) s.destruct
- stream.seq.take 0 s = list.nil
- stream.seq.take._match_1 _f_1 (option.some (x, r)) = x :: _f_1 r
- stream.seq.take._match_1 _f_1 option.none = list.nil
Split a sequence at n
, producing a finite initial segment
and an infinite tail.
Equations
- stream.seq.split_at (n + 1) s = stream.seq.split_at._match_1 (λ (s' : stream.seq α), stream.seq.split_at n s') s.destruct
- stream.seq.split_at 0 s = (list.nil α, s)
- stream.seq.split_at._match_1 _f_1 (option.some (x, s')) = stream.seq.split_at._match_2 x (_f_1 s')
- stream.seq.split_at._match_1 _f_1 option.none = (list.nil α, stream.seq.nil α)
- stream.seq.split_at._match_2 x (l, r) = (x :: l, r)
Combine two sequences with a function
Equations
- stream.seq.zip_with f s₁ s₂ = ⟨λ (n : ℕ), option.map₂ f (s₁.nth n) (s₂.nth n), _⟩
Pair two sequences into a sequence of pairs
Equations
Separate a sequence of pairs into two sequences
Equations
- s.unzip = (stream.seq.map prod.fst s, stream.seq.map prod.snd s)
Enumerate a sequence by tagging each element with its index.
Equations
- s.enum = stream.seq.nats.zip s
Convert a sequence which is known to terminate into a list
Equations
- s.to_list h = stream.seq.take (nat.find h) s
Convert a sequence which is known not to terminate into a stream
Equations
- s.to_stream h = λ (n : ℕ), option.get _
Convert a sequence into either a list or a stream depending on whether it is finite or infinite. (Without decidability of the infiniteness predicate, this is not constructively possible.)
Equations
- s.to_list_or_stream = dite s.terminates (λ (h : s.terminates), sum.inl (s.to_list h)) (λ (h : ¬s.terminates), sum.inr (s.to_stream h))
Equations
- stream.seq.functor = {map := stream.seq.map, map_const := λ (α β : Type u_1), stream.seq.map ∘ function.const β}
Convert a sequence into a list, embedded in a computation to allow for the possibility of infinite sequences (in which case the computation never returns anything).
Equations
- s.to_list' = computation.corec (λ (_x : list α × stream.seq α), stream.seq.to_list'._match_2 _x) (list.nil α, s)
- stream.seq.to_list'._match_2 (l, s) = stream.seq.to_list'._match_1 l s.destruct
- stream.seq.to_list'._match_1 l (option.some (a, s')) = sum.inr (a :: l, s')
- stream.seq.to_list'._match_1 l option.none = sum.inl l.reverse
Convert a seq1
to a sequence.
Equations
- stream.seq1.to_seq (a, s) = stream.seq.cons a s
Equations
Map a function on a seq1
Equations
- stream.seq1.map f (a, s) = (f a, stream.seq.map f s)
Flatten a nonempty sequence of nonempty sequences
Equations
- stream.seq1.join ((a, s), S) = stream.seq1.join._match_3 a S s.destruct
- stream.seq1.join._match_3 a S (option.some s') = (a, (stream.seq.cons s' S).join)
- stream.seq1.join._match_3 a S option.none = (a, S.join)
The return
operator for the seq1
monad,
which produces a singleton sequence.
Equations
- stream.seq1.ret a = (a, stream.seq.nil α)
Equations
The bind
operator for the seq1
monad,
which maps f
on each element of s
and appends the results together.
(Not all of s
may be evaluated, because the first few elements of s
may already produce an infinite result.)
Equations
- s.bind f = (stream.seq1.map f s).join