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; a no-op if x is already present.

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