HQL collections¶
HQL distinguishes membership, positions and lookup through collection contracts
and concrete carriers. Their declarations are in std/collections.hql.
| Type | Intended meaning | Design consequence |
|---|---|---|
Collection<T> |
Finite occurrences with membership and multiplicity | No positional order or uniqueness promise |
Set<T> |
Unordered collection of distinct elements | No implicit first element or stable iteration order |
Seq<T> |
Positionally ordered sequence, allowing repeated elements | Positions are observable; the elements need not be orderable |
List<T> |
A Seq<T> held entirely in memory |
Length is known; a second traversal is free |
Map<K, V> |
Values associated with distinct keys | Lookup is by key; iteration order is not implied |
Sets deduplicate using HQL equality, and cards compare by document identity.
Maps reject duplicate keys and return Option<V> for lookup. OrderedMap
preserves key positions; SortedMap orders those positions by intrinsic key
order. See the collection model for
the hierarchy and contracts.
Cards are a set¶
cards : Set<Card>
This is a type statement for the context value, not a proposed standalone
declaration syntax. cards represents the current vault or namespace. Sorting
can establish a sequence; merely discovering files must not establish a language
ordering guarantee. Selecting a reproducible prefix requires a defined order,
including how equal sort keys are handled.
cards is inferred as Set<Card>. Sorting it produces List<Card>, which
satisfies Seq<Card>, without an explicit conversion:
open = cards | filter(c => c.metadata.status == "todo")
open | sort(by = c => c.title) | map(c => c.title)
A prefix of a set is reproducible when its elements carry their own ordering key — see orderable.
List narrows Seq¶
type List<T> : Seq<T>
List is not an alias for Seq and not a second name for the same contract.
Seq<T> says a position exists for every element — each one can be assigned a
natural number — which a lazily produced sequence satisfies without ever being
materialized. List<T> adds that the elements are held rather than
produced: the collection is in memory, its length is known without consuming
it, and traversing it twice costs what traversing it once did. Every List is
therefore a Seq, and the narrowing is the usual one.
Seq<T> is an abstract type of law, and the narrowing asserts that
List satisfies it — see type-system, Abstract types of law.
Ordered is not orderable¶
Three words in this area are close enough to be confused, and they are three different things. This is settled, and the register matters as much as the vocabulary.
| Concept | What it says | Whose property |
|---|---|---|
Seq<T> |
Positional order. A position exists for every element: 0 → 42, 1 → 7, 2 → 19. |
the collection |
Orderable |
Value order. For any two values of the type, which comes first is determinable — ∀ a, b : T, a ≤ b can be decided. |
the element type |
SortedSeq<T> |
Both, and they agree. The positional order coincides with the value order. | the collection, relative to its elements |
The load-bearing sentence:
A sequence is ordered, but its elements need not be orderable.
Seq<Function> is the case that proves it. It has a first, a second and a third
element, and no two functions have a meaningful < between them. The positions
come from the sequence, not from the values — which is the exact mirror of
cards : Set<Card>, where the order comes from the values and not from the
collection.
So the phrase "Seq is orderable" is wrong and should not appear. A Seq is
ordered, or indexed. Orderable is reserved for a type whose values
possess an ordering relation. Sorting expects that relation to be total, or
the result is not determined.
Sorting is an operation, not a type property¶
"Sortable" names something a function can do with a collection, not a foundational property a type has. It is therefore a signature and not a supertype:
fn sort<T>(xs: Collection<T>) : List<T>
where T : Orderable
or, when the caller supplies the relation rather than the element type carrying it:
fn sort<T>(xs: Collection<T>, by: (T, T) -> Ordering) : List<T>
The second form is what makes Seq<Function> sortable without Function being
Orderable — the order arrives with the comparator. This is also why
[[orderable|Orderable]] stays a supertype rather than becoming a capability: it
says the values have a key, and supplying one from outside is the other
signature, not the same one narrowed.
Ordering is declared in std/core.hql. SortedSeq<T> remains a design name;
sorting currently returns List<T>. A key selector such as by = c => c.title
uses the selected key's intrinsic order. Equal keys retain their relative
positions in a sequence; unordered inputs have no prior positions to preserve.
Collection functions¶
Filtering, mapping, sorting and aggregation are typed operations used through
pipes or direct calls. Filtering a set preserves set semantics. Mapping
returns a list and retains repeated outputs; Set(result) explicitly collapses
duplicates. Binding annotations are optional because the checker infers these
types from the input and the supplied lambda.
Unordered inputs give an executor room to partition pure work. Sequence order, duplicate behavior and aggregation laws constrain that freedom. A parallel execution strategy must preserve the result promised by the collection function.
See hql/core for the type vocabulary and hql/knowledge for semantic identity.