Set

Set k

Provides a set type which stores a collection of unique values, without any ordering

empty : {} -> Set *

Creates a new empty Set.

empty_set = Set.empty({})
count_values = Set.len(empty_set)

expect count_values == 0

with_capacity : U64 -> Set *

Return a set with space allocated for a number of entries. This may provide a performance optimization if you know how many entries will be inserted.

reserve : Set k, U64 -> Set k

Enlarge the set for at least capacity additional elements

release_excess_capacity : Set k -> Set k

Shrink the memory footprint of a set such that capacity is as small as possible. This function will require regenerating the metadata if the size changes. There will still be some overhead due to dictionary metadata always being a power of 2.

single : k -> Set k

Creates a new Set with a single value.

single_item_set = Set.single("Apple")
count_values = Set.len(single_item_set)

expect count_values == 1

insert : Set k, k -> Set k

Insert a value into a Set.

few_item_set =
    Set.empty({})
    |> Set.insert("Apple")
    |> Set.insert("Pear")
    |> Set.insert("Banana")

count_values = Set.len(few_item_set)

expect count_values == 3

len : Set * -> U64

Counts the number of values in a given Set.

few_item_set =
    Set.empty({})
    |> Set.insert("Apple")
    |> Set.insert("Pear")
    |> Set.insert("Banana")

count_values = Set.len(few_item_set)

expect count_values == 3

capacity : Set * -> U64

Returns the max number of elements the set can hold before requiring a rehash.

food_set =
    Set.empty({})
    |> Set.insert("apple")

capacity_of_set = Set.capacity(food_set)

is_empty : Set * -> Bool

Check if the set is empty.

Set.is_empty(Set.empty({}) |> Set.insert(42))

Set.is_empty(Set.empty({}))

remove : Set k, k -> Set k

Removes the value from the given Set.

numbers =
    Set.empty({})
    |> Set.insert(10)
    |> Set.insert(20)
    |> Set.remove(10)

has10 = Set.contains(numbers, 10)
has20 = Set.contains(numbers, 20)

expect has10 == Bool.false
expect has20 == Bool.true

contains : Set k, k -> Bool

Test if a value is in the Set.

Fruit : [Apple, Pear, Banana]

fruit : Set Fruit
fruit =
    Set.single(Apple)
    |> Set.insert(Pear)

has_apple = Set.contains(fruit, Apple)
has_banana = Set.contains(fruit, Banana)

expect has_apple == Bool.true
expect has_banana == Bool.false

to_list : Set k -> List k

Retrieve the values in a Set as a List.

numbers : Set U64
numbers = Set.from_list([1,2,3,4,5])

values = [1,2,3,4,5]

expect Set.to_list(numbers) == values

from_list : List k -> Set k

Create a Set from a List of values.

values =
    Set.empty({})
    |> Set.insert(Banana)
    |> Set.insert(Apple)
    |> Set.insert(Pear)

expect Set.from_list([Pear, Apple, Banana]) == values

union : Set k, Set k -> Set k

Combine two Set collection by keeping the union of all the values pairs. This means that all of the values in both Sets will be combined.

set1 = Set.single(Left)
set2 = Set.single(Right)

expect Set.union(set1, set2) == Set.from_list([Left, Right])

intersection : Set k, Set k -> Set k

Combine two Sets by keeping the intersection of all the values pairs. This means that we keep only those values that are in both Sets.

set1 = Set.from_list([Left, Other])
set2 = Set.from_list([Left, Right])

expect Set.intersection(set1, set2) == Set.single(Left)

difference : Set k, Set k -> Set k

Remove the values in the first Set that are also in the second Set using the set difference of the values. This means that we will be left with only those values that are in the first and not in the second.

first = Set.from_list([Left, Right, Up, Down])
second = Set.from_list([Left, Right])

expect Set.difference(first, second) == Set.from_list([Up, Down])

walk : Set k, state, (state, k -> state) -> state

Iterate through the values of a given Set and build a value.

values = Set.from_list(["March", "April", "May"])

starts_with_letter_m = \month ->
    when Str.to_utf8(month) is
        ['M', ..] -> Bool.true
        _ -> Bool.false

reduce = \state, k ->
    if starts_with_letter_m(k) then
        state + 1
    else
        state

result = Set.walk(values, 0, reduce)

expect result == 2

map : Set a, (a -> b) -> Set b

Convert each value in the set to something new, by calling a conversion function on each of them which receives the old value. Then return a new set containing the converted values.

join_map : Set a, (a -> Set b) -> Set b

Like Set.map, except the transformation function wraps the return value in a set. At the end, all the sets get joined together (using Set.union) into one set.

You may know a similar function named concat_map in other languages.

walk_until : Set k, state, (state, k -> [ Continue state, Break state ]) -> state

Iterate through the values of a given Set and build a value, can stop iterating part way through the collection.

numbers = Set.from_list([1,2,3,4,5,6,42,7,8,9,10])

find42 = \state, k ->
    if k == 42 then
        Break(FoundTheAnswer)
    else
        Continue(state)

result = Set.walk_until(numbers, NotFound, find42)

expect result == FoundTheAnswer

keep_if : Set k, (k -> Bool) -> Set k

Run the given function on each element in the Set, and return a Set with just the elements for which the function returned Bool.true.

expect Set.from_list([1,2,3,4,5])
    |> Set.keep_if(\k -> k >= 3)
    |> Bool.is_eq(Set.from_list([3,4,5]))

drop_if : Set k, (k -> Bool) -> Set k

Run the given function on each element in the Set, and return a Set with just the elements for which the function returned Bool.false.

expect Set.from_list [1,2,3,4,5]
    |> Set.drop_if(\k -> k >= 3)
    |> Bool.is_eq(Set.from_list([1,2]))