add Hash and Eq to Dict and Set

This commit is contained in:
Brendan Hansknecht 2023-05-24 10:38:47 -07:00
parent 9b58c0fb9c
commit 877be563ba
No known key found for this signature in database
GPG key ID: 0EA784685083E75B
2 changed files with 121 additions and 2 deletions

View file

@ -98,6 +98,30 @@ Dict k v := {
data : List (T k v),
size : Nat,
} | k has Hash & Eq
has [
Eq {
isEq,
},
Hash {
hash: hashDict,
},
]
isEq : Dict k v, Dict k v -> Bool | k has Hash & Eq, v has Eq
isEq = \xs, ys ->
if len xs != len ys then
Bool.false
else
walkUntil xs Bool.true \_, k, xVal ->
when get ys k is
Ok yVal if yVal == xVal ->
Continue Bool.true
_ ->
Break Bool.false
hashDict : hasher, Dict k v -> hasher | k has Hash & Eq, v has Hash, hasher has Hasher
hashDict = \hasher, dict -> Hash.hashUnordered hasher (toList dict) List.walk
## Return an empty dictionary.
## ```
@ -747,6 +771,71 @@ expect
val == Ok "bar"
expect
dict1 =
empty {}
|> insert 1 "bar"
|> insert 2 "baz"
dict2 =
empty {}
|> insert 2 "baz"
|> insert 1 "bar"
dict1 == dict2
expect
dict1 =
empty {}
|> insert 1 "bar"
|> insert 2 "baz"
dict2 =
empty {}
|> insert 1 "bar"
|> insert 2 "baz!"
dict1 != dict2
expect
inner1 =
empty {}
|> insert 1 "bar"
|> insert 2 "baz"
inner2 =
empty {}
|> insert 2 "baz"
|> insert 1 "bar"
outer =
empty {}
|> insert inner1 "wrong"
|> insert inner2 "right"
get outer inner1 == Ok "right"
expect
inner1 =
empty {}
|> insert 1 "bar"
|> insert 2 "baz"
inner2 =
empty {}
|> insert 2 "baz"
|> insert 1 "bar"
outer1 =
empty {}
|> insert inner1 "val"
outer2 =
empty {}
|> insert inner2 "val"
outer1 == outer2
expect
val =
empty {}

View file

@ -20,7 +20,7 @@ interface Set
Bool.{ Bool, Eq },
Dict.{ Dict },
Num.{ Nat },
Hash.{ Hash },
Hash.{ Hash, Hasher },
]
# We should have this line above the next has.
@ -28,11 +28,14 @@ interface Set
# | k has Hash & Eq
## Provides a [set](https://en.wikipedia.org/wiki/Set_(abstract_data_type))
## type which stores a collection of unique values, without any ordering
Set k := Dict.Dict k {}
Set k := Dict.Dict k {} | k has Hash & Eq
has [
Eq {
isEq,
},
Hash {
hash: hashSet,
},
]
isEq : Set k, Set k -> Bool | k has Hash & Eq
@ -46,6 +49,9 @@ isEq = \xs, ys ->
else
Break Bool.false
hashSet : hasher, Set k -> hasher | k has Hash & Eq, hasher has Hasher
hashSet = \hasher, @Set inner -> Hash.hash hasher inner
## Creates a new empty `Set`.
## ```
## emptySet = Set.empty {}
@ -353,3 +359,27 @@ expect
|> insert 9
x == fromList (toList x)
# TODO: This test that puts a Set in a Set fails to unify.
# expect
# orderOne : Set Nat
# orderOne =
# single 1
# |> insert 2
# orderTwo : Set Nat
# orderTwo =
# single 2
# |> insert 1
# wrapperOne : Set (Set Nat)
# wrapperOne =
# single orderOne
# |> insert orderTwo
# wrapperTwo : Set (Set Nat)
# wrapperTwo =
# single orderTwo
# |> insert orderOne
# wrapperOne == wrapperTwo