Mathematical types (seq, set, mset, dict
)
This section gives an overview of the mathematical types supported by Gobra and their operations. Examples illustrate the syntax and the operations.
Note that mathematical types are ghost types and may only be used in ghost code.
Sequences (seq
)
The type seq[T]
represents finite sequences with elements of type T
.
expression E | type of x | type of y | result type of E | description |
---|---|---|---|---|
x ++ y | seq[T] | seq[T] | seq[T] | concatenation |
x[i] | seq[T] | T | lookup the element at index i 1 | |
x == y | seq[T] | seq[T] | bool | equality |
x in y | T | seq[T] | bool | true if and only if x is an element of y |
seq[T]{} | seq[T] | empty sequence | ||
seq[T]{x, y} | T | T | seq[T] | literal2 |
seq[x..y] | I | I | seq[I] 3 | integer sequence \( [x, x+1, \ldots, y-1] \) |
len(x) | seq[T] | int | length | |
x[i = y] | seq[T] | T | seq[T] | creates a sequence with element y at index i , otherwise identical to x . 1 |
x[i:j] | seq[T] | seq[T] | sub-sequence 4 | |
seq(x) | seq[T] | seq[T] | conversion from a sequence | |
seq(x) | seq[T] | [N]T | conversion from an array of length N |
The indices i
and j
are of integer type. Requires 0 <= i && i < len(x)
.
Sequence literals can be constructed with an arbitrary number of elements. The table only contains an example for two elements.
I
is an arbitrary integer type (byte
, uint8
, int
, ...)
Sub-sequence with elements between index i
(inclusive) and index j
(exclusive). If i < 0
or i
is omitted, the lower index is treated as 0. If j > len(x)
or j
is omitted, the upper index is treated as len(x)
.
Example: seq[int]
// The empty sequence
empty := seq[int]{}
// Length of the sequence
assert len(empty) == 0
// Constructing from a literal
s := seq[int]{0, 1, 1, 2, 3}
// Membership check
assert 1 in s && !(4 in s)
// Lookup
assert s[4] == 3
// Integer sequence shorthand
s1 := seq[0..5]
// Comparison
assert seq[0..5] == seq[int]{0, 1, 2, 3, 4}
// Works also with other integer types such as byte
assert seq[0..2] == seq[byte]{byte(0), byte(1)}
assert seq[4..2] == seq[int]{}
s2 := seq[5..10]
s3 := seq[0..10]
// Concatentation of sequences with ++
assert s1 ++ s2 == s3
// Subsequences
assert s3[0:5] == s1
// Omitting the first index
assert s3[:5] == s1
// Omitting both indices
assert s3[:] == s3
// No well-defined requirements for sub-sequence indices
assert len(s3[5:1]) == 0
assert len(s3[-10:20]) == 10
// Conversion from an array
arr := [5]int{0, 1, 2, 3, 4}
s4 := seq(arr)
// Conversion from another sequence
assert s4 == seq(s4)
s5 := seq[int]{0, 0, 0}
// Create from sequence with update
s6 := s5[0 = 2]
// The original sequence is not modified (it is immutable)
assert s6[0] == 2 && s5[0] == 0
assert s5[0 = 2][1 = 4][2 = 8] == seq[int]{2, 4, 8}
Sets (set
)
The type set[T]
represents mathematical sets with elements of type T
.
expression E | type of x | type of y | result type of E | description |
---|---|---|---|---|
set[T]{} | set[T] | \( \varnothing \) | ||
set[T]{x, y} | T | T | set[T] | \( \{x, y \} \), in general with an arbitrary number of elements. |
x union y | set[T] | set[T] | set[T] | \( x \cup y \) |
x intersection y | set[T] | set[T] | set[T] | \( x \cap y \) |
x setminus y | set[T] | set[T] | set[T] | \( x \setminus y\) |
x subset y | set[T] | set[T] | bool | \( x \subseteq y\) |
x == y | set[T] | set[T] | bool | \( x = y\) |
x in y | T | set[T] | bool | \( x \in y\) |
len(x) | set[T] | int | \( |x| \) | |
x # y | T | set[T] | int | 1 if \(x \in y\) else 0 |
set(x) | set[T] | set[T] | conversion from a set | |
set(x) | seq[T] | set[T] | conversion from a sequence |
Example: set[int]
// The empty set
empty := seq[int]{}
s1 := set[int]{1, 2, 3}
s2 := set[int]{1, 2, 2, 3, 3, 3}
// Equality
assert s1 == s2
// Cardinality
assert len(s1) == len(s2)
// Conversion from a sequence
s3 := set(seq[int]{ 1, 2})
// Conversion from a set
s4 := set(s1)
// Membership
assert 1 in set[int]{1, 2} && !(0 in set[int]{1, 2})
// Set operations
assert set[int]{0, 2} subset set[int]{0, 1, 2}
assert set[int]{0, 2} union set[int]{1} == set[int]{0, 1, 2}
assert set[int]{0, 1} intersection set[int]{1, 2} == set[int]{1}
assert set[int]{0, 1} setminus set[int]{1, 2} == set[int]{0}
Multisets (mset
)
The type mset[T]
represents multisets with elements of type T
.
Multisets are like sets but may contain the same element multiple times.
The multiset operations respect the multiplicities of the elements.
expression E | type of x | type of y | result type of E | description |
---|---|---|---|---|
mset[T]{} | mset[T] | |||
mset[T]{x, x} | T | T | mset[T] | \( \{x, x \} \), in general with an arbitrary number of elements. |
x union y | mset[T] | mset[T] | mset[T] | |
x intersection y | mset[T] | mset[T] | mset[T] | |
x setminus y | mset[T] | mset[T] | mset[T] | |
x subset y | mset[T] | mset[T] | bool | |
x == y | mset[T] | mset[T] | bool | |
x in y | T | mset[T] | bool | |
len(x) | mset[T] | int | ||
x # y | T | mset[T] | int | multiplicity of the element x in y |
mset(x) | mset[T] | mset[T] | conversion from a multiset | |
mset(x) | seq[T] | mset[T] | conversion from a sequence |
Example: mset[int]
m1 := mset[int]{1, 2, 3}
m2 := mset[int]{1, 2, 2, 3, 3, 3}
assert len(m1) == 3 && len(m2) == 6
// Multiplicity
assert 3 # m1 == 1 && 3 # m2 == 3
assert 4 # m1 == 0
// multiset operations
assert mset[int]{0, 1} union mset[int]{1} == mset[int]{0, 1, 1}
assert mset[int]{1, 1, 1} intersection mset[int]{1, 1, 2} == mset[int]{1, 1}
assert mset[int]{1, 1, 2} setminus mset[int]{1, 2, 2} == mset[int]{1}
assert mset[int]{1} subset mset[int]{1, 1}
assert !(mset[int]{1, 1} subset mset[int]{1})
Dictionaries (dict
)
The type dict[K]V
represents dictionaries with keys of type K
and values of type V
.
expression E | type of x | type of y | result type of E | description |
---|---|---|---|---|
dict[K]V{} | dict[K]V | empty dict | ||
dict[K]V{x: y} | K | V | dict[K]V | dict literal 5 |
x == y | dict[K]V | dict[K]V | bool | equality |
x[y] | dict[K]V | K | V | lookup the value associated with key y 6 |
m[x = y] | K | V | dict[K]V | dict with additional mapping (x, y) , otherwise identical to the dict m |
len(x) | dict[K]V | int | number of keys | |
domain(x) | dict[K]V | set[K] | set of keys | |
range(x) | dict[K]V | set[V] | set of values |
In general, more items may be given. For duplicate keys, an error is reported:
m1 := dict[string]int{ "one": 1, "two": 2, "one": -1}
ERROR key appears twice in map literal
m1 := dict[string]int{ "one": 1, "two": 2, "one": -1}
^
Requires y in domain(x)
. Otherwise, an error is reported:
m1 := dict[string]int{ "one": 1, "two": 2}
assert m1["three"] == 3
ERROR Assert might fail.
Key "three" might not be contained in m1.
Example: dict[string]int
m1 := dict[string]int{ "one": 1, "two": 2}
assert m1["one"] == 1
assert len(m1) == 2
assert domain(m1) == set[string]{"one", "two"}
assert range(m1) == set[int]{1, 2}
// update dict
m2 := m1["three" = 3, "four" = 4]
// syntactic sugar for
m2 = m2["zwei" = 2]
m2["zwei"] = 2
assert m2["zwei"] == 2 && m2["three"] == 3 && m2["four"] == 4