Struct Seq

Source
pub struct Seq<A> { /* private fields */ }
Expand description

Seq<A> is a sequence type for specifications. To use a “sequence” in compiled code, use an exec type like vec::Vec that has Seq<A> as its specification type.

An object seq: Seq<A> has a length, given by seq.len(), and a value at each i for 0 <= i < seq.len(), given by seq[i].

Sequences can be constructed in a few different ways:

  • Seq::empty construct an empty sequence (len() == 0)
  • Seq::new construct a sequence of a given length, initialized according to a given function mapping indices i to values A.
  • The seq! macro, to construct small sequences of a fixed size (analagous to the std::vec! macro).
  • By manipulating an existing sequence with Seq::push, Seq::update, or Seq::add.

To prove that two sequences are equal, it is usually easiest to use the extensional equality operator =~=.

Implementations§

Source§

impl<A> Seq<A>

Source

pub uninterp fn empty() -> Seq<A>

An empty sequence (i.e., a sequence of length 0).

Source

pub uninterp fn new(len: nat, f: impl Fn(int) -> A) -> Seq<A>

Construct a sequence s of length len where entry s[i] is given by f(i).

Source

pub uninterp fn len(self) -> nat

The length of a sequence.

Source

pub uninterp fn index(self, i: int) -> A

recommends
0 <= i < self.len(),

Gets the value at the given index i.

If i is not in the range [0, self.len()), then the resulting value is meaningless and arbitrary.

Source

pub open spec fn spec_index(self, i: int) -> A

recommends
0 <= i < self.len(),
{ self.index(i) }

[] operator, synonymous with index

Source

pub uninterp fn push(self, a: A) -> Seq<A>

Appends the value a to the end of the sequence. This always increases the length of the sequence by 1. This often requires annotating the type of the element literal in the sequence, e.g., 10int.

§Example
proof fn push_test() {
    assert(seq![10int, 11, 12].push(13) =~= seq![10, 11, 12, 13]);
}
Source

pub uninterp fn update(self, i: int, a: A) -> Seq<A>

recommends
0 <= i < self.len(),

Updates the sequence at the given index, replacing the element with the given value, and leaves all other entries unchanged.

§Example
proof fn update_test() {
    let s = seq![10, 11, 12, 13, 14];
    let t = s.update(2, -5);
    assert(t =~= seq![10, 11, -5, 13, 14]);
}
Source

pub uninterp fn subrange(self, start_inclusive: int, end_exclusive: int) -> Seq<A>

recommends
0 <= start_inclusive <= end_exclusive <= self.len(),

Returns a sequence for the given subrange.

§Example
proof fn subrange_test() {
    let s = seq![10int, 11, 12, 13, 14];
    //                      ^-------^
    //           0      1   2   3   4   5
    let sub = s.subrange(2, 4);
    assert(sub =~= seq![12, 13]);
}
Source

pub open spec fn take(self, n: int) -> Seq<A>

{ self.subrange(0, n) }

Returns a sequence containing only the first n elements of the original sequence

Source

pub open spec fn skip(self, n: int) -> Seq<A>

{ self.subrange(n, self.len() as int) }

Returns a sequence without the first n elements of the original sequence

Source

pub uninterp fn add(self, rhs: Seq<A>) -> Seq<A>

Concatenates the sequences.

§Example
proof fn add_test() {
    assert(seq![10int, 11].add(seq![12, 13, 14])
            =~= seq![10, 11, 12, 13, 14]);
}
Source

pub open spec fn spec_add(self, rhs: Seq<A>) -> Seq<A>

{ self.add(rhs) }

+ operator, synonymous with add

Source

pub open spec fn last(self) -> A

recommends
0 < self.len(),
{ self[self.len() as int - 1] }

Returns the last element of the sequence.

Source

pub open spec fn first(self) -> A

recommends
0 < self.len(),
{ self[0] }

Returns the first element of the sequence.

Source

pub proof fn tracked_empty() -> tracked ret : Self

ensures
ret === Seq::empty(),
Source

pub proof fn tracked_remove(tracked &mut self, i: int) -> tracked ret : A

requires
0 <= i < old(self).len(),
ensures
ret === old(self)[i],
self.len() == old(self).len() - 1,
self == old(self).remove(i),
Source

pub proof fn tracked_insert(tracked &mut self, i: int, tracked v: A)

requires
0 <= i <= old(self).len(),
ensures
self.len() == old(self).len() + 1,
self == old(self).insert(i, v),
Source

pub proof fn tracked_borrow(tracked &self, i: int) -> tracked ret : &A

requires
0 <= i < self.len(),
ensures
*ret === self[i],
Source

pub proof fn tracked_push(tracked &mut self, tracked v: A)

ensures
*self == old(self).push(v),
self.len() == old(self).len() + 1,
Source

pub proof fn tracked_pop(tracked &mut self) -> tracked ret : A

requires
old(self).len() > 0,
ensures
ret === old(self).last(),
self.len() == old(self).len() - 1,
*self == old(self).take(old(self).len() - 1),
Source

pub proof fn tracked_pop_front(tracked &mut self) -> tracked ret : A

requires
old(self).len() > 0,
ensures
ret === old(self).first(),
self.len() == old(self).len() - 1,
*self == old(self).drop_first(),
Source§

impl<A> Seq<A>

Source

pub open spec fn map<B>(self, f: FnSpec<(int, A), B>) -> Seq<B>

{ Seq::new(self.len(), |i: int| f(i, self[i])) }

Applies the function f to each element of the sequence, and returns the resulting sequence. The int parameter of f is the index of the element being mapped.

Source

pub open spec fn map_values<B>(self, f: FnSpec<(A,), B>) -> Seq<B>

{ Seq::new(self.len(), |i: int| f(self[i])) }

Applies the function f to each element of the sequence, and returns the resulting sequence.

Source

pub open spec fn flat_map<B>(self, f: FnSpec<(A,), Seq<B>>) -> Seq<B>

{ self.map_values(f).flatten() }

Applies the function f to each element of the sequence, producing a sequence of sequences, and then concatenates (flattens) those into a single flat sequence of B.

§Example
fn example() {
    let s = seq![1, 2, 3];
    let result = s.flat_map(|x| seq![x, x]);
    assert_eq!(result, seq![1, 1, 2, 2, 3, 3]);
}
``
Source

pub open spec fn is_prefix_of(self, other: Self) -> bool

{ self.len() <= other.len() && (self =~= other.subrange(0, self.len() as int)) }

Is true if the calling sequence is a prefix of the given sequence ‘other’.

§Example
proof fn prefix_test() {
    let pre: Seq<int> = seq![1, 2, 3];
    let whole: Seq<int> = seq![1, 2, 3, 4, 5];
    assert(pre.is_prefix_of(whole));
}
Source

pub open spec fn is_suffix_of(self, other: Self) -> bool

{
    self.len() <= other.len()
        && (self
            =~= other.subrange((other.len() - self.len()) as int, other.len() as int))
}

Is true if the calling sequence is a suffix of the given sequence ‘other’.

§Example
proof fn suffix_test() {
    let end: Seq<int> = seq![3, 4, 5];
    let whole: Seq<int> = seq![1, 2, 3, 4, 5];
    assert(end.is_suffix_of(whole));
}
Source

pub closed spec fn sort_by(self, leq: FnSpec<(A, A), bool>) -> Seq<A>

recommends
total_ordering(leq),

Sorts the sequence according to the given leq function

§Example
{{#include ../../../../examples/multiset.rs:sorted_by_leq}}
Source

pub open spec fn all(self, pred: FnSpec<(A,), bool>) -> bool

{ forall |i: int| 0 <= i < self.len() ==> #[trigger] pred(self[i]) }

Tests if all elements in the sequence satisfy the predicate.

§Example
fn example() {
    let s = seq![2, 4, 6, 8];
    assert!(s.all(|x| x % 2 == 0));
}
Source

pub open spec fn any(self, pred: FnSpec<(A,), bool>) -> bool

{ exists |i: int| 0 <= i < self.len() && #[trigger] pred(self[i]) }

Tests if any element in the sequence satisfies the predicate.

§Example
fn example() {
    let s = seq![1, 2, 3, 4];
    assert!(s.any(|x| x > 3));
}
Source

pub open spec fn exactly_one(self, pred: FnSpec<(A,), bool>) -> bool

{ self.filter(pred).len() == 1 }

Checks that exactly one element in the sequence satisfies the given predicate.

§Example
fn example() {
    let s = seq![1, 2, 3];
    assert!(s.exactly_one(|x| x == 2));
}
Source

pub proof fn lemma_sort_by_ensures(self, leq: FnSpec<(A, A), bool>)

requires
total_ordering(leq),
ensures
self.to_multiset() =~= self.sort_by(leq).to_multiset(),
sorted_by(self.sort_by(leq), leq),
forall |x: A| !self.contains(x) ==> !(#[trigger] self.sort_by(leq).contains(x)),
Source

pub open spec fn filter(self, pred: FnSpec<(A,), bool>) -> Self

{
    if self.len() == 0 {
        self
    } else {
        let subseq = self.drop_last().filter(pred);
        if pred(self.last()) { subseq.push(self.last()) } else { subseq }
    }
}

Returns the sequence containing only the elements of the original sequence such that pred(element) is true.

§Example
proof fn filter_test() {
   let seq: Seq<int> = seq![1, 2, 3, 4, 5];
   let even: Seq<int> = seq.filter(|x| x % 2 == 0);
   reveal_with_fuel(Seq::<int>::filter, 6); //Needed for Verus to unfold the recursive definition of filter
   assert(even =~= seq![2, 4]);
}
Source

pub broadcast proof fn lemma_filter_len(self, pred: FnSpec<(A,), bool>)

ensures
#[trigger] self.filter(pred).len() <= self.len(),
Source

pub broadcast proof fn lemma_filter_pred(self, pred: FnSpec<(A,), bool>, i: int)

requires
0 <= i < self.filter(pred).len(),
ensures
pred(#[trigger] self.filter(pred)[i]),
Source

pub broadcast proof fn lemma_filter_contains(self, pred: FnSpec<(A,), bool>, i: int)

requires
0 <= i < self.len() && pred(self[i]),
ensures
#[trigger] self.filter(pred).contains(self[i]),
Source

pub proof fn filter_lemma(self, pred: FnSpec<(A,), bool>)

👎Deprecated: Use broadcast use group_filter_ensures instead
ensures
forall |i: int| {
    0 <= i < self.filter(pred).len() ==> pred(#[trigger] self.filter(pred)[i])
},
forall |i: int| {
    0 <= i < self.len() && pred(self[i]) ==> #[trigger]
        self.filter(pred).contains(self[i])
},
#[trigger] self.filter(pred).len() <= self.len(),
Source

pub broadcast proof fn filter_distributes_over_add(a: Self, b: Self, pred: FnSpec<(A,), bool>)

ensures
#[trigger] (a + b).filter(pred) == a.filter(pred) + b.filter(pred),
Source

pub broadcast proof fn add_empty_left(a: Self, b: Self)

requires
a.len() == 0,
ensures
#[trigger] (a + b) == b,
Source

pub broadcast proof fn add_empty_right(a: Self, b: Self)

requires
b.len() == 0,
ensures
#[trigger] (a + b) == a,
Source

pub broadcast proof fn push_distributes_over_add(a: Self, b: Self, elt: A)

ensures
#[trigger] (a + b).push(elt) == a + b.push(elt),
Source

pub open spec fn max_via(self, leq: FnSpec<(A, A), bool>) -> A

recommends
self.len() > 0,
{
    if self.len() > 1 {
        if leq(self[0], self.subrange(1, self.len() as int).max_via(leq)) {
            self.subrange(1, self.len() as int).max_via(leq)
        } else {
            self[0]
        }
    } else {
        self[0]
    }
}

Returns the maximum value in a non-empty sequence, given sorting function leq

Source

pub open spec fn min_via(self, leq: FnSpec<(A, A), bool>) -> A

recommends
self.len() > 0,
{
    if self.len() > 1 {
        let subseq = self.subrange(1, self.len() as int);
        let elt = subseq.min_via(leq);
        if leq(elt, self[0]) { elt } else { self[0] }
    } else {
        self[0]
    }
}

Returns the minimum value in a non-empty sequence, given sorting function leq

Source

pub open spec fn contains(self, needle: A) -> bool

{ exists |i: int| 0 <= i < self.len() && self[i] == needle }
Source

pub open spec fn index_of(self, needle: A) -> int

{ choose |i: int| 0 <= i < self.len() && self[i] == needle }

Returns an index where needle appears in the sequence. Returns an arbitrary value if the sequence does not contain the needle.

Source

pub closed spec fn index_of_first(self, needle: A) -> result : Option<int>

For an element that occurs at least once in a sequence, if its first occurence is at index i, Some(i) is returned. Otherwise, None is returned

Source

pub proof fn index_of_first_ensures(self, needle: A)

ensures
match self.index_of_first(needle) {
    Some(index) => (
        &&& self.contains(needle)
        &&& 0 <= index < self.len()
        &&& self[index] == needle
        &&& forall |j: int| 0 <= j < index < self.len() ==> self[j] != needle

    ),
    None => !self.contains(needle),
},
Source

pub closed spec fn index_of_last(self, needle: A) -> Option<int>

For an element that occurs at least once in a sequence, if its last occurence is at index i, Some(i) is returned. Otherwise, None is returned

Source

pub proof fn index_of_last_ensures(self, needle: A)

ensures
match self.index_of_last(needle) {
    Some(index) => (
        &&& self.contains(needle)
        &&& 0 <= index < self.len()
        &&& self[index] == needle
        &&& forall |j: int| 0 <= index < j < self.len() ==> self[j] != needle

    ),
    None => !self.contains(needle),
},
Source

pub open spec fn drop_last(self) -> Seq<A>

recommends
self.len() >= 1,
{ self.subrange(0, self.len() as int - 1) }

Drops the last element of a sequence and returns a sequence whose length is thereby 1 smaller.

If the input sequence is empty, the result is meaningless and arbitrary.

Source

pub proof fn drop_last_distributes_over_add(a: Self, b: Self)

requires
0 < b.len(),
ensures
(a + b).drop_last() == a + b.drop_last(),

Dropping the last element of a concatenation of a and b is equivalent to skipping the last element of b and then concatenating a and b

Source

pub open spec fn drop_first(self) -> Seq<A>

recommends
self.len() >= 1,
{ self.subrange(1, self.len() as int) }
Source

pub open spec fn no_duplicates(self) -> bool

{
    forall |i, j| {
        (0 <= i < self.len() && 0 <= j < self.len() && i != j) ==> self[i] != self[j]
    }
}

returns true if the sequence has no duplicate elements

Source

pub open spec fn disjoint(self, other: Self) -> bool

{
    forall |i: int, j: int| {
        0 <= i < self.len() && 0 <= j < other.len() ==> self[i] != other[j]
    }
}

Returns true if two sequences are disjoint

Source

pub open spec fn to_set(self) -> Set<A>

{ Set::new(|a: A| self.contains(a)) }

Converts a sequence into a set

Source

pub closed spec fn to_multiset(self) -> Multiset<A>

Converts a sequence into a multiset

Source

pub broadcast proof fn to_multiset_ensures(self)

ensures
forall |a: A| #[trigger] (self.push(a).to_multiset()) =~= self.to_multiset().insert(a),
forall |i: int| {
    0 <= i < self.len()
        ==> (#[trigger] (self.remove(i).to_multiset())
            =~= self.to_multiset().remove(self[i]))
},
self.len() == #[trigger] self.to_multiset().len(),
forall |a: A| self.contains(a) <==> #[trigger] self.to_multiset().count(a) > 0,

Proof of function to_multiset() correctness

Source

pub open spec fn insert(self, i: int, a: A) -> Seq<A>

recommends
0 <= i <= self.len(),
{ self.subrange(0, i).push(a) + self.subrange(i, self.len() as int) }

Insert item a at index i, shifting remaining elements (if any) to the right

Source

pub proof fn insert_ensures(self, pos: int, elt: A)

requires
0 <= pos <= self.len(),
ensures
self.insert(pos, elt).len() == self.len() + 1,
forall |i: int| 0 <= i < pos ==> #[trigger] self.insert(pos, elt)[i] == self[i],
forall |i: int| pos <= i < self.len() ==> self.insert(pos, elt)[i + 1] == self[i],
self.insert(pos, elt)[pos] == elt,

Proof of correctness and expected properties of insert function

Source

pub open spec fn remove(self, i: int) -> Seq<A>

recommends
0 <= i < self.len(),
{ self.subrange(0, i) + self.subrange(i + 1, self.len() as int) }

Remove item at index i, shifting remaining elements to the left

Source

pub proof fn remove_ensures(self, i: int)

requires
0 <= i < self.len(),
ensures
self.remove(i).len() == self.len() - 1,
forall |index: int| 0 <= index < i ==> #[trigger] self.remove(i)[index] == self[index],
forall |index: int| {
    i <= index < self.len() - 1 ==> #[trigger] self.remove(i)[index] == self[index + 1]
},

Proof of function remove() correctness

Source

pub open spec fn remove_value(self, val: A) -> Seq<A>

{
    let index = self.index_of_first(val);
    match index {
        Some(i) => self.remove(i),
        None => self,
    }
}

If a given element occurs at least once in a sequence, the sequence without its first occurrence is returned. Otherwise the same sequence is returned.

Source

pub open spec fn reverse(self) -> Seq<A>

{
    if self.len() == 0 {
        Seq::empty()
    } else {
        Seq::new(self.len(), |i: int| self[self.len() - 1 - i])
    }
}

Returns the sequence that is in reverse order to a given sequence.

Source

pub open spec fn zip_with<B>(self, other: Seq<B>) -> Seq<(A, B)>

recommends
self.len() == other.len(),
{
    if self.len() != other.len() {
        Seq::empty()
    } else if self.len() == 0 {
        Seq::empty()
    } else {
        Seq::new(self.len(), |i: int| (self[i], other[i]))
    }
}

Zips two sequences of equal length into one sequence that consists of pairs. If the two sequences are different lengths, returns an empty sequence

Source

pub open spec fn fold_left<B>(self, b: B, f: FnSpec<(B, A), B>) -> res : B

{ if self.len() == 0 { b } else { f(self.drop_last().fold_left(b, f), self.last()) } }

Folds the sequence to the left, applying f to perform the fold.

Equivalent to Iterator::fold in Rust.

Given a sequence s = [x0, x1, x2, ..., xn], applying this function s.fold_left(b, f) returns f(...f(f(b, x0), x1), ..., xn).

Source

pub open spec fn fold_left_alt<B>(self, b: B, f: FnSpec<(B, A), B>) -> res : B

{
    if self.len() == 0 {
        b
    } else {
        self.subrange(1, self.len() as int).fold_left_alt(f(b, self[0]), f)
    }
}

Equivalent to Self::fold_left but defined by breaking off the leftmost element when recursing, rather than the rightmost. See Self::lemma_fold_left_alt that proves equivalence.

Source

pub broadcast proof fn lemma_fold_left_split<B>(self, b: B, f: FnSpec<(B, A), B>, k: int)

requires
0 <= k <= self.len(),
ensures
self
    .subrange(k, self.len() as int)
    .fold_left((#[trigger] self.subrange(0, k).fold_left(b, f)), f)
    == self.fold_left(b, f),

A lemma that proves how Self::fold_left distributes over splitting a sequence.

Source

pub proof fn lemma_fold_left_alt<B>(self, b: B, f: FnSpec<(B, A), B>)

ensures
self.fold_left(b, f) == self.fold_left_alt(b, f),

Self::fold_left and Self::fold_left_alt are equivalent.

Source

pub proof fn lemma_reverse_fold_left<B>(self, v: B, f: FnSpec<(B, A), B>)

ensures
self.reverse().fold_left(v, f) == self.fold_right(|a: A, b: B| f(b, a), v),

Self::fold_left on the reversed sequence is equivalent to Self::fold_right on the original sequence with corresponding folding operator

Source

pub open spec fn fold_right<B>(self, f: FnSpec<(A, B), B>, b: B) -> res : B

{ if self.len() == 0 { b } else { self.drop_last().fold_right(f, f(self.last(), b)) } }

Folds the sequence to the right, applying f to perform the fold.

Equivalent to DoubleEndedIterator::rfold in Rust.

Given a sequence s = [x0, x1, x2, ..., xn], applying this function s.fold_right(b, f) returns f(x0, f(x1, f(x2, ..., f(xn, b)...))).

Source

pub open spec fn fold_right_alt<B>(self, f: FnSpec<(A, B), B>, b: B) -> res : B

{
    if self.len() == 0 {
        b
    } else {
        f(self[0], self.subrange(1, self.len() as int).fold_right_alt(f, b))
    }
}

Equivalent to Self::fold_right but defined by breaking off the leftmost element when recursing, rather than the rightmost. See Self::lemma_fold_right_alt that proves equivalence.

Source

pub broadcast proof fn lemma_fold_right_split<B>(self, f: FnSpec<(A, B), B>, b: B, k: int)

requires
0 <= k <= self.len(),
ensures
self
    .subrange(0, k)
    .fold_right(f, (#[trigger] self.subrange(k, self.len() as int).fold_right(f, b)))
    == self.fold_right(f, b),

A lemma that proves how Self::fold_right distributes over splitting a sequence.

Source

pub proof fn lemma_fold_right_commute_one<B>(self, a: A, f: FnSpec<(A, B), B>, v: B)

requires
commutative_foldr(f),
ensures
self.fold_right(f, f(a, v)) == f(a, self.fold_right(f, v)),
Source

pub proof fn lemma_fold_right_alt<B>(self, f: FnSpec<(A, B), B>, b: B)

ensures
self.fold_right(f, b) == self.fold_right_alt(f, b),

Self::fold_right and Self::fold_right_alt are equivalent.

Source

pub proof fn lemma_reverse_fold_right<B>(self, v: B, f: FnSpec<(A, B), B>)

ensures
self.reverse().fold_right(f, v) == self.fold_left(v, |b: B, a: A| f(a, b)),

Self::fold_right on the reversed sequence is equivalent to Self::fold_left on the original sequence with corresponding folding operator

Source

pub proof fn lemma_multiset_has_no_duplicates(self)

requires
self.no_duplicates(),
ensures
forall |x: A| self.to_multiset().contains(x) ==> self.to_multiset().count(x) == 1,

Given a sequence with no duplicates, each element occurs only once in its conversion to a multiset

Source

pub proof fn lemma_multiset_has_no_duplicates_conv(self)

requires
forall |x: A| self.to_multiset().contains(x) ==> self.to_multiset().count(x) == 1,
ensures
self.no_duplicates(),

If, in a sequence’s conversion to a multiset, each element occurs only once, the sequence has no duplicates.

Source

pub proof fn lemma_reverse_to_multiset(self)

ensures
self.reverse().to_multiset() =~= self.to_multiset(),

Conversion of a sequence to multiset is equivalent to conversion of its reversion to multiset

Source

pub proof fn lemma_add_last_back(self)

requires
0 < self.len(),
ensures
#[trigger] self.drop_last().push(self.last()) =~= self,

The concatenation of two subsequences derived from a non-empty sequence, the first obtained from skipping the last element, the second consisting only of the last element, is the original sequence.

Source

pub proof fn lemma_indexing_implies_membership(self, f: FnSpec<(A,), bool>)

requires
forall |i: int| 0 <= i < self.len() ==> #[trigger] f(#[trigger] self[i]),
ensures
forall |x: A| #[trigger] self.contains(x) ==> #[trigger] f(x),

If a predicate is true at every index of a sequence, it is true for every member of the sequence as a collection. Useful for converting quantifiers between the two forms to satisfy a precondition in the latter form.

Source

pub proof fn lemma_membership_implies_indexing(self, f: FnSpec<(A,), bool>)

requires
forall |x: A| #[trigger] self.contains(x) ==> #[trigger] f(x),
ensures
forall |i: int| 0 <= i < self.len() ==> #[trigger] f(self[i]),

If a predicate is true for every member of a sequence as a collection, it is true at every index of the sequence. Useful for converting quantifiers between the two forms to satisfy a precondition in the latter form.

Source

pub proof fn lemma_split_at(self, pos: int)

requires
0 <= pos <= self.len(),
ensures
self.subrange(0, pos) + self.subrange(pos, self.len() as int) =~= self,

A sequence that is sliced at the pos-th element, concatenated with that same sequence sliced from the pos-th element, is equal to the original unsliced sequence.

Source

pub proof fn lemma_element_from_slice(self, new: Seq<A>, a: int, b: int, pos: int)

requires
0 <= a <= b <= self.len(),
new == self.subrange(a, b),
a <= pos < b,
ensures
pos - a < new.len(),
new[pos - a] == self[pos],

Any element in a slice is included in the original sequence.

Source

pub proof fn lemma_slice_of_slice(self, s1: int, e1: int, s2: int, e2: int)

requires
0 <= s1 <= e1 <= self.len(),
0 <= s2 <= e2 <= e1 - s1,
ensures
self.subrange(s1, e1).subrange(s2, e2) =~= self.subrange(s1 + s2, s1 + e2),

A slice (from s2..e2) of a slice (from s1..e1) of a sequence is equal to just a slice (s1+s2..s1+e2) of the original sequence.

Source

pub proof fn unique_seq_to_set(self)

requires
self.no_duplicates(),
ensures
self.len() == self.to_set().len(),

A sequence of unique items, when converted to a set, produces a set with matching length

Source

pub proof fn lemma_cardinality_of_set(self)

ensures
self.to_set().len() <= self.len(),

The cardinality of a set of elements is always less than or equal to that of the full sequence of elements.

Source

pub proof fn lemma_cardinality_of_empty_set_is_0(self)

ensures
self.to_set().len() == 0 <==> self.len() == 0,

A sequence is of length 0 if and only if its conversion to a set results in the empty set.

Source

pub proof fn lemma_no_dup_set_cardinality(self)

requires
self.to_set().len() == self.len(),
ensures
self.no_duplicates(),

A sequence with cardinality equal to its set has no duplicates. Inverse property of that shown in lemma unique_seq_to_set

Source

pub broadcast proof fn lemma_to_set_map_commutes<B>(self, f: FnSpec<(A,), B>)

ensures
#[trigger] self.to_set().map(f) =~= self.map_values(f).to_set(),

Mapping a function over a sequence and converting to a set is the same as mapping it over the sequence converted to a set.

Source

pub broadcast proof fn lemma_to_set_insert_commutes(sq: Seq<A>, elt: A)

ensures
#[trigger] (sq + seq![elt]).to_set() =~= sq.to_set().insert(elt),

Appending an element to a sequence and converting to set, is equal to converting to set and inserting it.

Source

pub open spec fn update_subrange_with(self, off: int, vs: Self) -> Self

recommends
0 <= off,
off + vs.len() <= self.len(),
{
    Seq::new(
        self.len(),
        |i: int| if off <= i < off + vs.len() { vs[i - off] } else { self[i] },
    )
}

Update a subrange of a sequence starting at off to values vs. Expects that the updated subrange off up to off+vs.len() fits in the existing sequence.

Source

pub broadcast proof fn lemma_seq_skip_skip(self, i: int)

ensures
0 <= i < self.len() ==> ((self.skip(i)).skip(1) =~= #[trigger] self.skip(i + 1)),

Skipping i elements and then 1 more is equivalent to skipping i + 1 elements.

§Example
proof fn example() {
    let s = seq![1, 2, 3, 4];
    s.lemma_seq_skip_skip(2);
    assert(s.skip(2).skip(1) =~= s.skip(3));
}
Source

pub proof fn lemma_contains_to_index(self, elem: A) -> idx : int

requires
self.contains(elem),
ensures
0 <= idx < self.len() && self[idx] == elem,

If an element is contained in a sequence, then there exists an index where that element appears.

§Example
proof fn example() {
    let s = seq![10, 20, 30];
    assert(s.contains(20));
    let idx = s.lemma_contains_to_index(20);
    assert(s[idx] == 20);
}
Source

pub proof fn lemma_all_from_head_tail(self, pred: FnSpec<(A,), bool>)

requires
self.len() > 0,
pred(self[0]) && self.skip(1).all(|x| pred(x)),
ensures
self.all(|x| pred(x)),

If a predicate holds for the first element and for all elements in the tail, then it holds for the entire sequence.

§Example
proof fn example() {
    let s = seq![2, 4, 6, 8];
    let is_even = |x| x % 2 == 0;
    assert(is_even(s[0]));
    assert(s.skip(1).all(is_even));
    s.lemma_all_from_head_tail(is_even);
    assert(s.all(is_even));
}
Source

pub proof fn lemma_any_tail(self, pred: FnSpec<(A,), bool>)

requires
self.any(|x| pred(x)),
ensures
!pred(self[0]) ==> self.skip(1).any(|x| pred(x)),

If a predicate holds for any element in the sequence and does not hold for the first element, then the predicate must hold for some element in the tail.

§Example
proof fn example() {
    let s = seq![1, 4, 6, 8];
    let is_even = |x| x % 2 == 0;
    assert(s.any(is_even));
    assert(!is_even(s[0]));
    s.lemma_any_tail(is_even);
    assert(s.skip(1).any(is_even));
}
Source

pub open spec fn remove_duplicates(self, seen: Seq<A>) -> Seq<A>

{
    if self.len() == 0 {
        seen
    } else if seen.contains(self[0]) {
        self.skip(1).remove_duplicates(seen)
    } else {
        self.skip(1).remove_duplicates(seen + seq![self[0]])
    }
}

Removes duplicate elements from a sequence, maintaining the order of first appearance. Takes a seen sequence parameter to track previously encountered elements.

§Example
fn example() {
    let s = seq![1, 2, 1, 3, 2, 4];
    let seen = seq![];
    let result = s.remove_duplicates(seen);
    assert_eq!(result, seq![1, 2, 3, 4]);

    let seen2 = seq![2, 3];
    let result2 = s.remove_duplicates(seen2);
    assert_eq!(result2, seq![1, 4]);
}
Source

pub broadcast proof fn lemma_remove_duplicates_properties(self, seen: Seq<A>)

ensures
forall |x| {
    (self + seen).contains(x) <==> #[trigger] self.remove_duplicates(seen).contains(x)
},
#[trigger] self.remove_duplicates(seen).len() <= self.len() + seen.len(),

Properties of remove_duplicates:

  • The output contains x if and only if x was in the input sequence or seen set
  • The output length is at most the sum of input and seen lengths
§Example
proof fn example() {
    let s = seq![1, 2, 1, 3];
    let seen = seq![2];
    s.lemma_remove_duplicates_properties(seen);
    assert(s.remove_duplicates(seen).contains(1));
    assert(s.remove_duplicates(seen).contains(3));
    assert(!s.remove_duplicates(seen).contains(2));
    assert(s.remove_duplicates(seen).len() <= s.len() + seen.len());
}
Source

pub proof fn lemma_remove_duplicates_append_index(self, i: int, seen: Seq<A>)

requires
0 <= i < self.len(),
ensures
self.remove_duplicates(seen)
    == self.skip(i).remove_duplicates(self.take(i).remove_duplicates(seen)),

Shows that removing duplicates from a sequence is equivalent to:

  1. First removing duplicates from the prefix up to index i (with the given seen set)
  2. Using that result as the new seen set for removing duplicates from the suffix after i
§Example
proof fn example() {
    let s = seq![1, 2, 1, 3, 2, 4];
    let seen = seq![];
    s.lemma_remove_duplicates_append_index(seen, 2);
    assert(s.remove_duplicates(seen)
        =~= seq![1, 3, 2, 4].remove_duplicates(seq![1, 2].remove_duplicates(seen)));
}
Source

pub proof fn lemma_remove_duplicates_append(self, x: A, seen: Seq<A>)

ensures
(self + seen).contains(x)
    ==> (self + seq![x]).remove_duplicates(seen) == self.remove_duplicates(seen),
!(self + seen).contains(x)
    ==> (self + seq![x]).remove_duplicates(seen)
        == self.remove_duplicates(seen) + seq![x],

When appending an element x to a sequence:

  • If x is in self + seen, removing duplicates equals removing duplicates from self
  • If x is not in (self + seen), removing duplicates equals removing duplicates from self, concatenated with [x]
§Example
proof fn example() {
    let s1 = seq![1, 2];
    let seen = seq![];
    assert!(!s1.contains(3));
    lemma_remove_duplicates_append(s1, 3, seen);
    assert((s1 + seq![3]).remove_duplicates(seen) =~= s1.remove_duplicates(seen) + seq![3]);
}
Source

pub proof fn lemma_all_neg_filter_empty(self, pred: FnSpec<(A,), bool>)

requires
self.all(|x: A| !pred(x)),
ensures
self.filter(pred).len() == 0,

If all elements in a sequence fail the predicate, filtering by that predicate yields an empty sequence

§Example
proof fn example() {
    let s = seq![1, 2, 3];
    let pred = |x| x > 5;
    lemma_all_neg_filter_empty(s, pred);
    assert(s.filter(pred).len() == 0);
}
Source

pub open spec fn filter_map<B>(self, f: FnSpec<(A,), Option<B>>) -> Seq<B>

{
    if self.len() == 0 {
        Seq::empty()
    } else {
        let rest = self.drop_last();
        match f(self.last()) {
            Option::Some(s) => rest.filter_map(f) + seq![s],
            Option::None => rest.filter_map(f),
        }
    }
}

Applies an Option-returning function to each element, keeping only successful (Some) results

§Example
let s = seq![1, 2, 3];
let f = |x| if x % 2 == 0 { Some(x * 2) } else { None };
assert(s.filter_map(f) =~= seq![4]);
Source

pub broadcast proof fn lemma_filter_contains_rev(self, p: FnSpec<(A,), bool>, elem: A)

requires
#[trigger] self.filter(p).contains(elem),
ensures
self.contains(elem),

If an element exists in the filtered sequence, it must exist in the original sequence

Source

pub broadcast proof fn lemma_filter_map_contains<B>(self, f: FnSpec<(A,), Option<B>>, elt: B)

requires
#[trigger] self.filter_map(f).contains(elt),
ensures
exists |t: A| #[trigger] self.contains(t) && f(t) == Some(elt),

If an element exists in filter_map’s output, there must be an input element that mapped to it

Source

pub proof fn lemma_take_succ(xs: Seq<A>, k: int)

requires
0 <= k < xs.len(),
ensures
xs.take(k + 1) =~= xs.take(k) + seq![xs[k]],

Taking k+1 elements is the same as taking k elements plus the kth element

§Example
let s = seq![1, 2, 3];
lemma_take_plus_one(s, 1);
seq![1, 2] == seq![1] + seq![2]
Source

pub proof fn lemma_filter_map_singleton<B>(a: A, f: FnSpec<(A,), Option<B>>)

ensures
seq![a].filter_map(f)
    =~= match f(a) {
        Option::Some(b) => seq![b],
        Option::None => Seq::empty(),
    },

filter_map on a single element sequence either produces a new single element sequence (if f returns Some) or an empty sequence (if f returns None)

Source

pub broadcast proof fn lemma_filter_map_take_succ<B>(self, f: FnSpec<(A,), Option<B>>, i: int)

requires
0 <= i < self.len(),
ensures
#[trigger] self.take(i + 1).filter_map(f)
    =~= self.take(i).filter_map(f)
        + (match f(self[i]) {
            Option::Some(s) => seq![s],
            Option::None => Seq::empty(),
        }),

filter_map of take(i+1) equals filter_map of take(i) plus maybe the mapped i’th element

§Example
let s = seq![1, 2, 3];
let f = |x| if x % 2 == 0 { Some(x * 2) } else { None };
s.lemma_filter_map_take_succ(s, f, 1);
assert(s.take(2).filter_map(f) == s.take(1).filter_map(f) + seq![f(s[1]).unwrap()]);
assert(s.take(2).filter_map(f) == seq![] + seq![4]);
Source

pub open spec fn filter_alt(self, p: FnSpec<(A,), bool>) -> Seq<A>

{
    if self.len() == 0 {
        Seq::empty()
    } else {
        let rest = self.drop_first().filter(p);
        let first = self.first();
        if p(first) { seq![first] + rest } else { rest }
    }
}

An alternative implementation of filter that processes the sequence recursively from left to right, in contrast to the standard filter which processes from right to left.

Source

pub broadcast proof fn lemma_filter_prepend(self, x: A, p: FnSpec<(A,), bool>)

ensures
#[trigger] (seq![x] + self).filter(p)
    == (if p(x) { seq![x] } else { Seq::empty() }) + self.filter(p),

When filtering (x + sequence), if x satisfies the predicate, x is prepended to the filtered sequence. Otherwise, only the filtered sequence remains.

§Example
proof fn filter_prepend_test() {
    let s = seq![2, 3, 4];
    let is_even = |x: int| x % 2 == 0;
    let with_five = seq![5] + s;
    assert(with_five.filter(is_even) =~= seq![2, 4]); // 5 filtered out
    let with_six = seq![6] + s;
    assert(with_six.filter(is_even) =~= seq![6, 2, 4]); // 6 included
}
Source

pub proof fn lemma_filter_eq_filter_alt(self, p: FnSpec<(A,), bool>)

ensures
self.filter(p) =~= self.filter_alt(p),

The filter() and filter_alt() methods produce equivalent results for any sequence

Source

pub proof fn lemma_filter_monotone(self, ys: Seq<A>, p: FnSpec<(A,), bool>)

requires
self.is_prefix_of(ys),
ensures
self.filter(p).is_prefix_of(ys.filter(p)),

Filtering preserves the prefix relationship between sequences.

§Example
proof fn filter_monotone_test() {
    let s = seq![1, 2, 3];
    let ys = seq![1, 2, 3, 4, 5];
    let is_even = |x: int| x % 2 == 0;
    assert(s.is_prefix_of(ys));
    assert(s.filter(is_even).is_prefix_of(ys.filter(is_even)));
    assert(s.filter(is_even) =~= seq![2]);
    assert(ys.filter(is_even) =~= seq![2, 4]);
}
Source

pub proof fn lemma_filter_take_len(self, p: FnSpec<(A,), bool>, i: int)

requires
0 <= i <= self.len(),
ensures
self.filter(p).len() >= self.take(i).filter(p).len(),

The length of filter(take(i)) is never greater than the length of filter(entire_sequence).

§Example
proof fn filter_take_len_test() {
    let s = seq![1, 2, 3, 4, 5];
    let is_even = |x: int| x % 2 == 0;
    let i = 3;
    assert(s.take(i) =~= seq![1, 2, 3]);
    assert(s.take(i).filter(is_even) =~= seq![2]);
    assert(s.filter(is_even) =~= seq![2, 4]);
    assert(s.filter(is_even).len() >= s.take(i).filter(is_even).len());
}
Source

pub broadcast proof fn lemma_filter_len_push(self, p: FnSpec<(A,), bool>, elem: A)

ensures
#[trigger] self.push(elem).filter(p).len()
    == self.filter(p).len() + (if p(elem) { 1int } else { 0int }),

Filtering a prefix of a sequence produces the same number or fewer elements as filtering the entire sequence.

§Example
proof fn filter_take_len_test() {
    let s = seq![1, 2, 3, 4, 5];
    let is_even = |x: int| x % 2 == 0;
    assert(s.filter(is_even).len() >= s.take(3).filter(is_even).len());
}
Source

pub broadcast proof fn lemma_index_contains(self, i: int)

requires
0 <= i < self.len(),
ensures
self.contains(#[trigger] self[i]),

If an index i is valid for a sequence (0 ≤ i < len), then the element at that index is contained in the sequence.

Source

pub broadcast proof fn lemma_take_succ_push(self, i: int)

requires
0 <= i < self.len(),
ensures
#[trigger] self.take(i + 1) =~= self.take(i).push(self[i]),

Taking i+1 elements from a sequence is equivalent to taking i elements and then pushing the element at index i.

Source

pub broadcast proof fn lemma_take_len(self)

ensures
#[trigger] self.take(self.len() as int) == self,

Taking the full length of a sequence returns the sequence itself.

Source

pub broadcast proof fn lemma_take_any_succ(self, p: FnSpec<(A,), bool>, i: int)

requires
0 <= i < self.len(),
ensures
#[trigger] self.take(i + 1).any(p) <==> self.take(i).any(p) || p(self[i]),

Taking i+1 elements and checking if any element satisfies predicate p is equivalent to: either taking i elements and checking if any satisfies p, OR checking if the i-th element satisfies p.

§Example
proof fn take_any_succ_test() {
    let s = seq![1, 2, 3];
    let is_even = |x| x % 2 == 0;
    let i = 1;
    assert(s.take(i + 1).any(is_even) == (s.take(i).any(is_even) || is_even(s[i])));
}
Source

pub proof fn lemma_no_duplicates_injective<B>(self, f: FnSpec<(A,), B>)

requires
injective(f),
ensures
self.no_duplicates() <==> self.map_values(f).no_duplicates(),

A sequence has no duplicates iff mapping an injective function over it produces a sequence with no duplicates.

§Example
proof fn no_duplicates_injective_test() {
    let s = seq![1, 2];
    let f = |x| x + 1;  // injective function
    assert(s.no_duplicates() == s.map_values(f).no_duplicates());
}
Source

pub broadcast proof fn lemma_push_map_commute<B>(self, f: FnSpec<(A,), B>, x: A)

ensures
self.map_values(f).push(f(x)) =~= #[trigger] self.push(x).map_values(f),

Pushing an element and then mapping a function over a sequence is equivalent to mapping the function over the sequence and then pushing the function applied to that element.

§Example
proof fn push_map_test() {
    let s = seq![1, 2];
    let f = |x| x + 1;
    assert(s.push(3).map_values(f) =~= s.map_values(f).push(f(3)));
}
Source

pub broadcast proof fn lemma_push_to_set_commute(self, elem: A)

ensures
#[trigger] self.push(elem).to_set() =~= self.to_set().insert(elem),

Converting a sequence to a set after pushing an element is equivalent to converting to a set first and then inserting that element.

§Example
proof fn push_to_set_test() {
    let s = seq![1, 2];
    assert(s.push(3).to_set() =~= s.to_set().insert(3));
}
Source

pub broadcast proof fn lemma_filter_push(self, elem: A, pred: FnSpec<(A,), bool>)

ensures
#[trigger] self.push(elem).filter(pred)
    == if pred(elem) { self.filter(pred).push(elem) } else { self.filter(pred) },

Filtering a sequence after pushing an element is equivalent to: if the element satisfies the predicate, filter the sequence and push the element otherwise, just filter the sequence without the element.

§Example
proof fn filter_push_test() {
    let s = seq![1, 2];
    let is_even = |x| x % 2 == 0;
    assert(s.push(4).filter(is_even) == s.filter(is_even).push(4));
    assert(s.push(3).filter(is_even) == s.filter(is_even));
}
Source

pub proof fn lemma_zip_with_contains_index<B>(self, b: Seq<B>, i: int)

requires
0 <= i < self.len(),
self.len() == b.len(),
ensures
self.zip_with(b).contains((self[i], b[i])),

If two sequences have the same length and i is a valid index, then the pair (a[i], b[i]) is contained in their zip.

§Example
proof fn zip_contains_test() {
    let a = seq![1, 2];
    let b = seq!["a", "b"];
    assert(a.zip_with(b).contains((a[0], b[0])));
    assert(a.zip_with(b).contains((a[1], b[1])));
}
Source

pub proof fn lemma_zip_with_uncurry_all<B>(self, b: Seq<B>, f: FnSpec<(A, B), bool>)

requires
self.len() == b.len(),
ensures
self.zip_with(b).all(|p: (A, B)| f(p.0, p.1))
    <==> forall |i: int| 0 <= i < self.len() ==> f(self[i], b[i]),

Proves equivalence between checking a predicate over zipped sequences and checking corresponding elements by index. Requires sequences of equal length.

§Example
proof fn example() {
    let xs = seq![1, 2];
    let ys = seq![2, 3];
    let f = |x, y| x < y;
    assert(xs.zip_with(ys).all(|(x, y)| f(x, y)) <==>
           forall|i| 0 <= i < xs.len() ==> f(xs[i], ys[i]));
    // We can now prove specific index relationships
    assert(xs[0] < ys[0]); // 1 < 2
    assert(xs[1] < ys[1]); // 2 < 3
}
Source

pub proof fn lemma_flat_map_push<B>(self, f: FnSpec<(A,), Seq<B>>, elem: A)

ensures
self.push(elem).flat_map(f) =~= self.flat_map(f) + f(elem),

flat_mapping after pushing an element is the same as flat_mapping first and then appending f of that element.

§Example
proof fn example() {
    let xs = seq![1, 2];
    let f = |x| seq![x, x + 1];
    assert(xs.push(3).flat_map(f) =~= xs.flat_map(f) + f(3));
    // xs.push(3).flat_map(f)    = [1,2,2,3,3,4]
    // xs.flat_map(f) + f(3)     = [1,2,2,3] + [3,4]
}
Source

pub broadcast proof fn lemma_flat_map_take_append<B>(self, f: FnSpec<(A,), Seq<B>>, i: int)

requires
0 <= i < self.len(),
ensures
#[trigger] self.take(i + 1).flat_map(f) =~= self.take(i).flat_map(f) + f(self[i]),

flat_mapping a sequence up to index i+1 is equivalent to flat_mapping up to index i and appending f of the element at index i.

§Example
proof fn example() {
    let xs = seq![1, 2, 3];
    let f = |x| seq![x, x + 1];

    assert(xs.take(2).flat_map(f) =~= xs.take(1).flat_map(f) + f(xs[1]));
    // xs.take(2).flat_map(f)        = [1,2,2,3]
    // xs.take(1).flat_map(f) + f(2) = [1,2] + [2,3]
}
Source

pub broadcast proof fn lemma_flat_map_singleton<B>(self, f: FnSpec<(A,), Seq<B>>)

requires
#[trigger] self.len() == 1,
ensures
#[trigger] self.flat_map(f) == f(self[0]),

flat_mapping a sequence with a single element is equivalent to applying the function f to that element.

Source

pub broadcast proof fn lemma_map_take_succ<B>(self, f: FnSpec<(A,), B>, i: int)

requires
0 <= i < self.len(),
ensures
#[trigger] self.take(i + 1).map_values(f) =~= self.take(i).map_values(f).push(f(self[i])),

Mapping a sequence’s first i+1 elements equals mapping its first i elements plus f of the i-th element.

§Example
proof fn example() {
    let xs = seq![1, 2, 3];
    let f = |x| x * 2;

    assert(xs.take(2).map_values(f) =~= xs.take(1).map_values(f).push(f(xs[1])));
    // Left:  [1,2].map(f)          = [2,4]
    // Right: [1].map(f).push(f(2)) = [2].push(4)
}
Source

pub broadcast proof fn lemma_prefix_index_eq(self, prefix: Seq<A>)

requires
#[trigger] prefix.is_prefix_of(self),
ensures
forall |i: int| 0 <= i < prefix.len() ==> prefix[i] == self[i],

If a sequence is a prefix of another sequence, their elements match at all indices within the prefix length.

§Example
proof fn example() {
    let xs = seq![1, 2, 3];
    let prefix = seq![1, 2];
    assert(prefix.is_prefix_of(xs));
    assert(prefix[0] == xs[0] && prefix[1] == xs[1]);
}
Source

pub broadcast proof fn lemma_prefix_concat(self, prefix1: Seq<A>, prefix2: Seq<A>)

requires
#[trigger] (prefix1 + prefix2).is_prefix_of(self),
ensures
prefix1.is_prefix_of(self),

If a concatenated sequence (prefix1 + prefix2) is a prefix of another sequence, then prefix1 by itself is also a prefix of that sequence.

§Example
proof fn example() {
    let xs = seq![1, 2, 3, 4];
    let prefix1 = seq![1, 2];
    let prefix2 = seq![3];
    assert((prefix1 + prefix2).is_prefix_of(xs));
    assert(prefix1.is_prefix_of(xs));
}
Source

pub broadcast proof fn lemma_prefix_chain_contains(self, prefix1: Seq<A>, prefix2: Seq<A>, t: A)

requires
#[trigger] (prefix1 + seq![t]).is_prefix_of(self),
#[trigger] prefix1.is_prefix_of(prefix2),
prefix2.is_prefix_of(self),
prefix1 != prefix2,
!prefix1.contains(t),
ensures
prefix2.contains(t),

If prefix1 + [t] is a prefix of a sequence, prefix1 is a prefix of prefix2, prefix2 is a prefix of the sequence, prefix1 and prefix2 are different, and prefix1 doesn’t contain t, then prefix2 must contain t.

§Example
proof fn example() {
    let xs = seq![1, 2, 3, 4];
    let prefix1 = seq![1];
    let prefix2 = seq![1, 2];
    let t = 2;
    assert((prefix1 + seq![t]).is_prefix_of(xs));
    assert(prefix1.is_prefix_of(prefix2));
    assert(prefix2.is_prefix_of(xs));
    assert(prefix2.contains(t));
}
Source

pub broadcast proof fn lemma_prefix_append_unique(self, prefix1: Seq<A>, prefix2: Seq<A>, t: A)

requires
#[trigger] (prefix1 + seq![t]).is_prefix_of(self),
#[trigger] (prefix2 + seq![t]).is_prefix_of(self),
!prefix1.contains(t),
!prefix2.contains(t),
ensures
prefix1 == prefix2,

If prefix1 + [t] and prefix2 + [t] are both prefixes of a sequence, and neither prefix1 nor prefix2 contains t, then prefix1 equals prefix2.

Source

pub broadcast proof fn lemma_all_push(self, p: FnSpec<(A,), bool>, elem: A)

requires
self.all(p),
p(elem),
ensures
#[trigger] self.push(elem).all(p),

If a predicate p is true for all elements in a sequence, and p is true for an element e, then p remains true for all elements after pushing e to the sequence.

§Example
proof fn example() {
    let xs = seq![2, 4, 6];
    let is_even = |x| x % 2 == 0;
    assert(xs.all(is_even));
    assert(is_even(8));
    assert(xs.push(8).all(is_even));
}
Source

pub proof fn lemma_concat_injective(self, s1: Seq<A>, s2: Seq<A>)

ensures
(self + s1 == self + s2) <==> (s1 == s2),

Two sequences are equal when concatenated with the same prefix iff those two sequences are equal.

Source

pub broadcast group fn group_seq_extra()

broadcast group
Source§

impl<A, B> Seq<(A, B)>

Source

pub closed spec fn unzip(self) -> (Seq<A>, Seq<B>)

Unzips a sequence that contains pairs into two separate sequences.

Source

pub proof fn unzip_ensures(self)

ensures
self.unzip().0.len() == self.unzip().1.len(),
self.unzip().0.len() == self.len(),
self.unzip().1.len() == self.len(),
forall |i: int| {
    0 <= i < self.len()
        ==> (#[trigger] self.unzip().0[i], #[trigger] self.unzip().1[i]) == self[i]
},

Proof of correctness and expected properties of unzip function

Source

pub proof fn lemma_zip_of_unzip(self)

ensures
self.unzip().0.zip_with(self.unzip().1) =~= self,

Unzipping a sequence of sequences and then zipping the resulting two sequences back together results in the original sequence of sequences.

Source§

impl<A> Seq<Seq<A>>

Source

pub open spec fn flatten(self) -> Seq<A>

{
    if self.len() == 0 {
        Seq::empty()
    } else {
        self.first().add(self.drop_first().flatten())
    }
}

Flattens a sequence of sequences into a single sequence by concatenating subsequences, starting from the first element.

§Example
proof fn flatten_test() {
   let seq: Seq<Seq<int>> = seq![seq![1, 2, 3], seq![4, 5, 6], seq![7, 8, 9]];
   let flat: Seq<int> = seq.flatten();
   reveal_with_fuel(Seq::<Seq<int>>::flatten, 5); //Needed for Verus to unfold the recursive definition of flatten
   assert(flat =~= seq![1, 2, 3, 4, 5, 6, 7, 8, 9]);
}
Source

pub open spec fn flatten_alt(self) -> Seq<A>

{
    if self.len() == 0 {
        Seq::empty()
    } else {
        self.drop_last().flatten_alt().add(self.last())
    }
}

Flattens a sequence of sequences into a single sequence by concatenating subsequences in reverse order, i.e. starting from the last element. This is equivalent to a call to flatten, but with concatenation operation applied along the oppositive associativity for the sake of proof reasoning in that direction.

Source

pub proof fn lemma_flatten_one_element(self)

ensures
self.len() == 1 ==> self.flatten() == self.first(),

Flattening a sequence of a sequence x, where x has length 1, results in a sequence equivalent to the single element of x

Source

pub proof fn lemma_flatten_length_ge_single_element_length(self, i: int)

requires
0 <= i < self.len(),
ensures
self.flatten_alt().len() >= self[i].len(),

The length of a flattened sequence of sequences x is greater than or equal to any of the lengths of the elements of x.

Source

pub proof fn lemma_flatten_length_le_mul(self, j: int)

requires
forall |i: int| 0 <= i < self.len() ==> (#[trigger] self[i]).len() <= j,
ensures
self.flatten_alt().len() <= self.len() * j,

The length of a flattened sequence of sequences x is less than or equal to the length of x multiplied by a number greater than or equal to the length of the longest sequence in x.

Source

pub proof fn lemma_flatten_and_flatten_alt_are_equivalent(self)

ensures
self.flatten() =~= self.flatten_alt(),

Flattening sequences of sequences in order (starting from the beginning) and in reverse order (starting from the end) results in the same sequence.

Source

pub broadcast proof fn lemma_flatten_push(self, elem: Seq<A>)

ensures
#[trigger] self.push(elem).flatten() =~= self.flatten() + elem,

Flattening a sequence of sequences after pushing a new sequence is equivalent to concatenating that sequence to the original flattened result.

Source

pub broadcast proof fn lemma_flatten_singleton(self)

requires
#[trigger] self.len() == 1,
ensures
#[trigger] self.flatten() == self[0],

Flattening a sequence containing a single sequence yields that inner sequence.

Source

pub broadcast group fn group_seq_flatten()

broadcast group
Source§

impl Seq<int>

Source

pub open spec fn max(self) -> int

recommends
0 < self.len(),
{
    if self.len() == 1 {
        self[0]
    } else if self.len() == 0 {
        0
    } else {
        let later_max = self.drop_first().max();
        if self[0] >= later_max { self[0] } else { later_max }
    }
}

Returns the maximum integer value in a non-empty sequence of integers.

Source

pub proof fn max_ensures(self)

ensures
forall |x: int| self.contains(x) ==> x <= self.max(),
forall |i: int| 0 <= i < self.len() ==> self[i] <= self.max(),
self.len() == 0 || self.contains(self.max()),

Proof of correctness and expected properties for max function

Source

pub open spec fn min(self) -> int

recommends
0 < self.len(),
{
    if self.len() == 1 {
        self[0]
    } else if self.len() == 0 {
        0
    } else {
        let later_min = self.drop_first().min();
        if self[0] <= later_min { self[0] } else { later_min }
    }
}

Returns the minimum integer value in a non-empty sequence of integers.

Source

pub proof fn min_ensures(self)

ensures
forall |x: int| self.contains(x) ==> self.min() <= x,
forall |i: int| 0 <= i < self.len() ==> self.min() <= self[i],
self.len() == 0 || self.contains(self.min()),

Proof of correctness and expected properties for min function

Source

pub closed spec fn sort(self) -> Self

Source

pub proof fn lemma_sort_ensures(self)

ensures
self.to_multiset() =~= self.sort().to_multiset(),
sorted_by(self.sort(), |x: int, y: int| x <= y),
Source

pub proof fn lemma_subrange_max(self, from: int, to: int)

requires
0 <= from < to <= self.len(),
ensures
self.subrange(from, to).max() <= self.max(),

The maximum element in a non-empty sequence is greater than or equal to the maxima of its non-empty subsequences.

Source

pub proof fn lemma_subrange_min(self, from: int, to: int)

requires
0 <= from < to <= self.len(),
ensures
self.subrange(from, to).min() >= self.min(),

The minimum element in a non-empty sequence is less than or equal to the minima of its non-empty subsequences.

Auto Trait Implementations§

§

impl<A> Freeze for Seq<A>

§

impl<A> RefUnwindSafe for Seq<A>
where A: RefUnwindSafe,

§

impl<A> Send for Seq<A>
where A: Send,

§

impl<A> Sync for Seq<A>
where A: Sync,

§

impl<A> Unpin for Seq<A>
where A: Unpin,

§

impl<A> UnwindSafe for Seq<A>
where A: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.