@@ -180,19 +180,14 @@ one x = TypeRepMap (primArrayFromListN 1 [fa])
182Insert a value into a 'TypeRepMap'.
182Insert a value into a 'TypeRepMap'.
183+TypeRepMap optimizes for fast reads rather than inserts, as a trade-off inserts are @O(n)@.
184prop> size (insert v tm) >= size tm
185prop> size (insert v tm) >= size tm
185prop> member @a (insert (x :: f a) tm) == True
186prop> member @a (insert (x :: f a) tm) == True
188insert :: forall a f . Typeable a => f a -> TypeRepMap f -> TypeRepMap f
189insert :: forall a f . Typeable a => f a -> TypeRepMap f -> TypeRepMap f
189−insert x = fromTriples . addX . toTriples
190+insert = union . one
191− tripleX :: (Fingerprint, Any, Any)
192− tripleX@(fpX, _, _) = (calcFp @a, toAny x, unsafeCoerce $ typeRep @a)
194− addX :: [(Fingerprint, Any, Any)] -> [(Fingerprint, Any, Any)]
195− addX l = tripleX : deleteByFst fpX l
196{-# INLINE insert #-}
191{-# INLINE insert #-}
198-- Extract the kind of a type. We use it to work around lack of syntax for
193-- Extract the kind of a type. We use it to work around lack of syntax for
@@ -201,6 +196,9 @@ type KindOf (a :: k) = k
202{- | Delete a value from a 'TypeRepMap'.
197{- | Delete a value from a 'TypeRepMap'.
199+TypeRepMap optimizes for fast reads rather than modifications, as a trade-off deletes are
200+@O(n)@, with an @O(log(n))@ optimization for when the element is already missing.
204prop> size (delete @a tm) <= size tm
202prop> size (delete @a tm) <= size tm
205prop> member @a (delete @a tm) == False
203prop> member @a (delete @a tm) == False
@@ -213,7 +211,13 @@ False
215delete :: forall a (f :: KindOf a -> Type) . Typeable a => TypeRepMap f -> TypeRepMap f
213delete :: forall a (f :: KindOf a -> Type) . Typeable a => TypeRepMap f -> TypeRepMap f
216−delete = fromTriples . deleteByFst (typeFp @a) . toTriples
214+delete m
215+ -- Lookups are fast, so check if we even have the element first.
216+ | not (member @a m) = m
217+ -- We know we have the element, If the map has exactly one element, we can return the empty map
218+ | size m == 1 = empty
219+ -- Otherwise, filter out the element in linear time.
220+ | otherwise = fromSortedTriples . filter ((/= typeFp @a) . fst3) . toSortedTriples $ m
217{-# INLINE delete #-}
221{-# INLINE delete #-}
@@ -407,9 +411,6 @@ toSortedTriples tm = trip <$> ordering
407 ordering :: [ Int ]
411 ordering :: [ Int ]
408 ordering = generateOrderMapping (size tm)
412 ordering = generateOrderMapping (size tm)
410−deleteByFst :: Eq a => a -> [(a, b, c)] -> [(a, b, c)]
411−deleteByFst x = filter ((/= x) . fst3)
413nubByFst :: (Eq a) => [(a, b, c)] -> [(a, b, c)]
414nubByFst :: (Eq a) => [(a, b, c)] -> [(a, b, c)]
414nubByFst = nubBy ((==) `on` fst3)
415nubByFst = nubBy ((==) `on` fst3)