0 | module Data.HashMap.Internal
2 | import public Data.Hashable
3 | import Data.HashMap.Bits
4 | import Data.HashMap.Array
5 | import Data.HashMap.SparseArray
6 | import Decidable.Equality
25 | data HAMT : (key : Type) -> (val : key -> Type) -> Type where
26 | Leaf : (hash : Bits64) -> (k : key) -> (v : val k) -> HAMT key val
27 | Node : SparseArray (HAMT key val) -> HAMT key val
28 | Collision : (hash : Bits64) -> Array (
k ** val k)
-> HAMT key val
32 | getMask : (depth : Bits64) -> Bits64
33 | getMask depth = baseMask `shiftL` (depth * chunkSize)
39 | getIndex : (depth : Bits64) -> (hash : Bits64) -> Bits32
40 | getIndex depth hash = unsafeCast $
(getMask depth .&. hash) `shiftR` (depth * chunkSize)
43 | singletonWithHash : (hash : Bits64) -> (k : key) -> val k -> HAMT key val
44 | singletonWithHash = Leaf
47 | singleton : Hashable key => (k : key) -> val k -> HAMT key val
48 | singleton k x = singletonWithHash (hash k) k x
52 | {0 val : key -> Type}
53 | (keyEq : (x : key) -> (y : key) -> Bool)
55 | lookupEntry : (k : key) -> (idx : Bits32) -> List (
k ** val k)
-> Maybe (Bits32, (
k ** val k)
)
56 | lookupEntry k idx [] = Nothing
57 | lookupEntry k idx (entry :: xs) = if keyEq k entry.fst
58 | then Just (idx, entry)
59 | else lookupEntry k (idx + 1) xs
68 | lookupWithHash k0 hash0 depth (Leaf hash1 k1 val) = if hash0 == hash1
70 | then Just (
k1 ** val)
73 | lookupWithHash k0 hash0 depth (Node arr) =
74 | let idx = getIndex depth hash0
75 | in index idx arr >>=
76 | lookupWithHash k0 hash0 (assert_smaller depth $
depth + 1)
77 | lookupWithHash k0 hash0 depth (Collision hash1 arr) = if hash0 == hash1
79 | let arrL = toList arr
80 | in snd <$> lookupEntry k0 0 arrL
89 | lookup k hamt = lookupWithHash k (hash k) 0 hamt
94 | (tree0 : HAMT key val) ->
96 | (tree1 : HAMT key val) ->
100 | node2 hamt0 hash0 hamt1 hash1 depth =
101 | let idx0 = getIndex depth hash0
102 | idx1 = getIndex depth hash1
104 | then Node $
singleton
105 | (idx0, (node2 hamt0 hash0 hamt1 hash1 (assert_smaller depth $
depth + 1)))
106 | else Node $
doubleton (idx0, hamt0) (idx1, hamt1)
113 | (depth : Bits64) ->
116 | insertWithHash k0 val0 hash0 depth hamt@(Leaf hash1 k1 val1) =
118 | then node2 (singletonWithHash hash0 k0 val0) hash0 hamt hash1 depth
119 | else if keyEq k0 k1
120 | then Leaf hash0 k0 val0
121 | else Collision hash0 (fromList [(
k0 ** val0)
, (
k1 ** val1)
])
122 | insertWithHash k val hash0 depth (Node arr) =
123 | let idx = getIndex depth hash0
124 | in case index idx arr of
125 | Just hamt => Node $
set idx
126 | (insertWithHash k val hash0 (assert_smaller depth $
depth + 1) hamt)
128 | Nothing => Node $
set idx (singletonWithHash hash0 k val) arr
129 | insertWithHash k val hash0 depth hamt@(Collision hash1 arr) =
131 | then case lookupEntry k 0 (toList arr) of
132 | Just (idx, _) => Collision hash1 (update arr [(idx, (
k ** val)
)])
133 | Nothing => Collision hash1 (append (
k ** val)
arr)
134 | else node2 (singletonWithHash hash0 k val) hash0 hamt hash1 depth
143 | insert k x hamt = insertWithHash k x (hash k) 0 hamt
150 | (depth : Bits64) ->
152 | Maybe (HAMT key val)
153 | deleteWithHash k0 h0 depth hamt@(Leaf h1 k1 _) =
154 | if h0 == h1 && keyEq k0 k1
157 | deleteWithHash k hash depth hamt0@(Node arr) =
158 | let idx = getIndex depth hash
159 | in case index idx arr of
160 | Just hamt1 => case deleteWithHash k hash (depth + 1) (assert_smaller hamt0 hamt1) of
161 | Just hamt2 => Just $
Node $
set idx hamt2 arr
163 | let arr' = delete idx arr
164 | in case length arr' of
166 | 1 => case index arr'.array 0 of
167 | Just (Node _) => Just $
Node arr'
169 | _ => Just $
Node arr'
170 | Nothing => Just hamt0
171 | deleteWithHash k h0 depth hamt@(Collision h1 arr) =
173 | then case findIndex (keyEq k . fst) arr of
174 | Nothing => Just hamt
176 | let arr' = delete idx arr
177 | in case length arr' of
179 | 1 => map (\(
key ** val)
=> Leaf h1 key val) $
index arr' 0
180 | _ => Just $
Collision h1 arr'
188 | Maybe (HAMT key val)
189 | delete k hamt = deleteWithHash k (hash k) 0 hamt
192 | trieMap : ({k : _} -> val0 k -> val1 k) -> HAMT key val0 -> HAMT key val1
193 | trieMap f (Leaf hash k v) = Leaf hash k (f v)
194 | trieMap f (Node arr) = Node $
assert_total $
map (trieMap f) arr
195 | trieMap f (Collision hash arr) = Collision hash $
map ({ snd $= f }) arr
198 | foldWithKey : ((k : _) -> val k -> acc -> acc) -> acc -> HAMT key val -> acc
199 | foldWithKey f z (Leaf hash k v) = f k v z
200 | foldWithKey f z (Node arr) = assert_total $
foldr (\trie, acc => foldWithKey f acc trie) z arr
201 | foldWithKey f z (Collision hash arr) = foldr (\(
k ** v)
, acc => f k v z) z arr