add Set implementation

This commit is contained in:
Brendan Hansknecht 2022-10-26 16:02:06 -07:00
parent cb08dca6f1
commit 02824e92fe
No known key found for this signature in database
GPG Key ID: 0EA784685083E75B
2 changed files with 45 additions and 38 deletions

View File

@ -96,7 +96,9 @@ Dict k v := {
dataIndices : List Nat,
data : List (T k v),
size : Nat,
} | k has Hash & Eq
}
# TODO: re-add type definition one #4408 is fixed
# | k has Hash & Eq
## Return an empty dictionary.
empty : Dict k v | k has Hash & Eq
@ -486,8 +488,7 @@ removeAll : Dict k v, Dict k v -> Dict k v | k has Hash & Eq
removeAll = \xs, ys ->
walk ys xs (\state, k, _ -> remove state k)
# TODO: re-add type definition one #4408 is fixed
# updateDataIndex : Dict k v, k, Nat -> Dict k v | k has Hash & Eq
updateDataIndex : Dict k v, k, Nat -> Dict k v | k has Hash & Eq
updateDataIndex = \@Dict { metadata, dataIndices, data, size }, key, dataIndex ->
hashKey =
createLowLevelHasher {}
@ -514,8 +515,8 @@ insertNotFoundHelper : Dict k v, k, v, U64, I8 -> Dict k v
insertNotFoundHelper = \@Dict { metadata, dataIndices, data, size }, key, value, h1Key, h2Key ->
probe = newProbe h1Key (div8 (List.len metadata))
index = nextEmptyOrDeletedHelper metadata probe 0
dataIndex = List.len data
nextData = List.append data (T key value)
dataIndex = List.len data - 1
@Dict {
metadata: List.set metadata index h2Key,

View File

@ -14,32 +14,40 @@ interface Set
intersection,
difference,
]
imports [List, Bool.{ Bool, Eq }, Dict.{ Dict }, Num.{ Nat }]
imports [
List,
Bool.{ Bool, Eq },
Dict.{ Dict },
Num.{ Nat },
Hash.{ Hasher, Hash },
]
Set k := Dict.Dict k {} has [Eq]
Set k := Dict.Dict k {}
# TODO: re-add type definition one #4408 is fixed
# | k has Hash & Eq
has [
Eq {
isEq,
},
]
fromDict : Dict k {} -> Set k
fromDict = \dict -> @Set dict
toDict : Set k -> Dict k {}
toDict = \@Set dict -> dict
isEq : Set k, Set k -> Bool | k has Hash & Eq
isEq = \_, _ -> Bool.true
## An empty set.
empty : Set k
empty = fromDict Dict.empty
empty : Set k | k has Hash & Eq
empty = @Set Dict.empty
single : k -> Set k
single : k -> Set k | k has Hash & Eq
single = \key ->
@Set (Dict.single key {})
Dict.single key {} |> @Set
## Make sure never to insert a *NaN* to a [Set]! Because *NaN* is defined to be
## unequal to *NaN*, adding a *NaN* results in an entry that can never be
## retrieved or removed from the [Set].
insert : Set k, k -> Set k | k has Eq
insert : Set k, k -> Set k | k has Hash & Eq
insert = \@Set dict, key ->
dict
|> Dict.insert key {}
|> @Set
Dict.insert dict key {} |> @Set
# Inserting a duplicate key has no effect.
expect
@ -58,7 +66,7 @@ expect
expected == actual
len : Set k -> Nat
len : Set k -> Nat | k has Hash & Eq
len = \@Set dict ->
Dict.len dict
@ -75,38 +83,36 @@ expect
actual == 3
## Drops the given element from the set.
remove : Set k, k -> Set k | k has Eq
remove : Set k, k -> Set k | k has Hash & Eq
remove = \@Set dict, key ->
@Set (Dict.remove dict key)
Dict.remove dict key |> @Set
contains : Set k, k -> Bool | k has Eq
contains = \set, key ->
set
|> Set.toDict
|> Dict.contains key
contains : Set k, k -> Bool | k has Hash & Eq
contains = \@Set dict, key ->
Dict.contains dict key
toList : Set k -> List k
toList : Set k -> List k | k has Hash & Eq
toList = \@Set dict ->
Dict.keys dict
fromList : List k -> Set k | k has Eq
fromList : List k -> Set k | k has Hash & Eq
fromList = \list ->
initial = @Set (Dict.withCapacity (List.len list))
List.walk list initial \set, key -> Set.insert set key
union : Set k, Set k -> Set k | k has Eq
union : Set k, Set k -> Set k | k has Hash & Eq
union = \@Set dict1, @Set dict2 ->
@Set (Dict.insertAll dict1 dict2)
Dict.insertAll dict1 dict2 |> @Set
intersection : Set k, Set k -> Set k | k has Eq
intersection : Set k, Set k -> Set k | k has Hash & Eq
intersection = \@Set dict1, @Set dict2 ->
@Set (Dict.keepShared dict1 dict2)
Dict.keepShared dict1 dict2 |> @Set
difference : Set k, Set k -> Set k | k has Eq
difference : Set k, Set k -> Set k | k has Hash & Eq
difference = \@Set dict1, @Set dict2 ->
@Set (Dict.removeAll dict1 dict2)
Dict.removeAll dict1 dict2 |> @Set
walk : Set k, state, (state, k -> state) -> state
walk = \set, state, step ->
Dict.walk (Set.toDict set) state (\s, k, _ -> step s k)
walk : Set k, state, (state, k -> state) -> state | k has Hash & Eq
walk = \@Set dict, state, step ->
Dict.walk dict state (\s, k, _ -> step s k)