A stream s : option α
is a sequence if s.nth n = none
implies s.nth (n + 1) = none
.
Equations
- s.is_seq = ∀ {n : ℕ}, s n = option.none → s (n + 1) = option.none
The empty sequence
Equations
Equations
- seq.inhabited = {default := seq.nil α}
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)
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
- seq.omap f (option.some (a, b)) = option.some (a, f b)
- seq.omap f option.none = option.none
Equations
- seq.has_mem = {mem := seq.mem α}
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
.
Equations
Equations
- seq.corec.F f (option.some b) = seq.corec.F._match_1 (f b)
- seq.corec.F f option.none = (option.none α, option.none β)
- seq.corec.F._match_1 (option.some (a, b')) = (option.some a, option.some b')
- 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
- seq.corec f b = ⟨stream.corec' (seq.corec.F f) (option.some b), _⟩
Embed a list as a sequence
Equations
- seq.of_list l = ⟨l.nth, _⟩
Equations
- seq.coe_list = {coe := seq.of_list α}
Equations
- seq.bisim_o R (option.some (a, s)) (option.some (a', s')) = (a = a' ∧ R s s')
- seq.bisim_o R (option.some (fst, snd)) option.none = false
- seq.bisim_o R option.none (option.some val) = false
- seq.bisim_o R option.none option.none = true
Equations
- seq.is_bisimulation R = ∀ ⦃s₁ s₂ : seq α⦄, R s₁ s₂ → seq.bisim_o R s₁.destruct s₂.destruct
Embed an infinite stream as a sequence
Equations
- seq.of_stream s = ⟨stream.map option.some s, _⟩
Equations
- seq.coe_stream = {coe := seq.of_stream α}
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
- seq.of_lazy_list = seq.corec (λ (l : lazy_list α), seq.of_lazy_list._match_1 l)
- seq.of_lazy_list._match_1 (lazy_list.cons a l') = option.some (a, l' ())
- seq.of_lazy_list._match_1 lazy_list.nil = option.none
Equations
Translate a sequence to a list. This function will run forever if run on an infinite sequence.
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₂ = seq.corec (λ (_x : seq α × seq α), seq.append._match_2 _x) (s₁, s₂)
- seq.append._match_2 (s₁, s₂) = seq.append._match_1 s₂ s₁.destruct
- seq.append._match_1 s₂ (option.some (a, s₁')) = option.some (a, s₁', s₂)
- seq.append._match_1 s₂ option.none = seq.omap (λ (s₂ : seq α), (seq.nil α, s₂)) s₂.destruct
Map a function over a sequence.
Equations
- 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
- seq.join = seq.corec (λ (S : seq (seq1 α)), seq.join._match_1 S.destruct)
- seq.join._match_1 (option.some ((a, s), S')) = option.some (a, seq.join._match_2 S' s.destruct)
- seq.join._match_1 option.none = option.none
- seq.join._match_2 S' (option.some s') = seq.cons s' S'
- seq.join._match_2 S' option.none = S'
Take the first n
elements of the sequence (producing a list)
Split a sequence at n
, producing a finite initial segment
and an infinite tail.
Equations
- seq.split_at (n + 1) s = seq.split_at._match_1 (λ (s' : seq α), seq.split_at n s') s.destruct
- seq.split_at 0 s = (list.nil α, s)
- seq.split_at._match_1 _f_1 (option.some (x, s')) = seq.split_at._match_2 x (_f_1 s')
- seq.split_at._match_1 _f_1 option.none = (list.nil α, seq.nil α)
- seq.split_at._match_2 x (l, r) = (x :: l, r)
Combine two sequences with a function
Equations
- seq.zip_with f ⟨f₁, a₁⟩ ⟨f₂, a₂⟩ = ⟨λ (n : ℕ), seq.zip_with._match_1 f (f₁ n) (f₂ n), _⟩
- seq.zip_with._match_1 f (option.some a) (option.some b) = option.some (f a b)
- seq.zip_with._match_1 f (option.some val) option.none = option.none
- seq.zip_with._match_1 f option.none _x = option.none
Equations
- seq.functor = {map := seq.map, map_const := λ (α β : Type u_1), seq.map ∘ function.const β}
Equations
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).
Convert a seq1
to a sequence.
Equations
- seq1.to_seq (a, s) = seq.cons a s
Equations
- seq1.coe_seq = {coe := seq1.to_seq α}
Flatten a nonempty sequence of nonempty sequences
Equations
- seq1.join ((a, s), S) = seq1.join._match_3 a S s.destruct
- seq1.join._match_3 a S (option.some s') = (a, (seq.cons s' S).join)
- seq1.join._match_3 a S option.none = (a, S.join)
Equations
- seq1.inhabited = {default := seq1.ret (inhabited.default α)}
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.)