hanki

set

stdlib/core/set.hk: Set<T>, a persistent set as a thin keys-only layer over the core Map HAMT.

Representation: Set<T> wraps Map<T, ()>. An element is a key whose value is unit, and membership, insertion and removal therefore reuse the tested HAMT and inherit its persistence (structural sharing) and O(log16 n) operations. Iteration order (to_list, Display) is hash order, unspecified and unstable, and never insertion order, as for the underlying Map.

Elements are bounded by Hash, whose Eq supertrait leaves == working; an element type must therefore be hashable. Eq/Hash/Display for the set itself are hand-written and not derived, the value type being unit and the set's identity is its element membership, order-independent: two sets are equal iff they hold the same elements, and hash accordingly.

The struct is opaque: the representation is private and can change without breaking callers.

Set

opaque Set<T>
  inner: Map<T, ()>
end

impl<T: Hash> Set<T>

empty

def empty() -> Set<T>

The empty set. The element type is fixed by the binding it flows into or by the first insert.

s: Set<i32> = Set.empty()
s.length => 0

from_list

def from_list(items: List<T>) -> Set<T>

A set of every element in items; duplicates collapse.

s = Set.from_list(List.empty().append(1i32).append(2i32).append(1i32))
s.length => 2

insert

def insert(self, x: T) -> Set<T>

self with x added, replacing any present element ==-equal to x.

Set.empty().insert(1i32).contains?(1i32) => true

contains?

def contains?(self, x: T) -> bool

Whether x is a member.

Set.empty().insert(1i32).contains?(2i32) => false

remove

def remove(self, x: T) -> Set<T>

self with x removed; a no-op if x is absent.

Set.empty().insert(1i32).remove(1i32).empty? => true

length

prop length(self) -> int

The number of elements.

Set.empty().insert(1i32).insert(2i32).length => 2

empty?

prop empty?(self) -> bool

Whether the set has no elements.

Set.empty().empty? => true

to_list

def to_list(self) -> List<T>

The elements as a list, in the underlying hash order.

Set.empty().insert(1i32).to_list().length => 1

union

def union(self, other: Set<T>) -> Set<T>

Every element in either set.

a = Set.empty().insert(1i32)
a.union(Set.empty().insert(2i32)).length => 2

intersection

def intersection(self, other: Set<T>) -> Set<T>

The elements in both sets.

a = Set.empty().insert(1i32).insert(2i32)
a.intersection(Set.empty().insert(2i32).insert(3i32)).length => 1

difference

def difference(self, other: Set<T>) -> Set<T>

The elements in self but not other.

a = Set.empty().insert(1i32).insert(2i32)
a.difference(Set.empty().insert(2i32)).length => 1

impl<T: Hash> Eq<Set<T>>

eq?

def eq?(self, other: Self) -> bool

Equal where both sets have the same elements.

Set.from_list(List.empty().append(1i32).append(2i32)) == Set.from_list(List.empty().append(2i32).append(1i32)) => true

impl<T: Hash> Hash<Set<T>>

hash

prop hash(self) -> u64

Hashes the value, which lets Set<T> key a Map or Set.

Set.from_list(List.empty().append(1i32).append(2i32)).hash == Set.from_list(List.empty().append(2i32).append(1i32)).hash => true

renderelems

def _render_elems<T: Display>(xs: List<T>) -> string

impl<T: Hash + Display> Display<Set<T>>

to_string

def to_string(self) -> string

Renders the set as {item, …} in element order.

@no-doctest: hash-order rendering is unspecified

_EncodedElement

struct _EncodedElement<T>
  key: bytes
  value: T
end

impl<T> Ord<_EncodedElement<T>>

cmp

def cmp(self, other: Self) -> Ordering

Orders by the element's encoded bytes.

@no-doctest: internal ordering helper for canonical Set encoding

encodedelement!

def _encoded_element!<T: Encode>(x: T) -> _EncodedElement<T>

encodedelements!

def _encoded_elements!<T: Encode>(xs: List<T>) -> List<_EncodedElement<T>>

emitelements!

def _emit_elements!<T: Encode, S: Serializer>(sorted: List<_EncodedElement<T>>, s: S) -> ()

impl<T: Hash + Encode> Encode<Set<T>>

encode!

def encode!<S: Serializer>(self, s: S) -> ()

Writes the elements as a sequence ordered by their encoded bytes.

a = Set.from_list(List.empty().append(1i32).append(2i32))
b = Set.from_list(List.empty().append(2i32).append(1i32))
codec.to_bytes(a) == codec.to_bytes(b) => true

setdecode!

def _set_decode!<T: Hash + Decode, D: Deserializer>(d: D, remaining: int, acc: Set<T>, depth: int) -> Result<Set<T>, DecodeError>

impl<T: Hash + Decode> Decode<Set<T>>

decode!

def decode!<D: Deserializer>(d: D, depth: int) -> Result<Set<T>, DecodeError>

Reads a sequence of elements back into a set.

@no-doctest: see the trait method in core/decode; the tests below round-trip through it