Improve performance of Relation.difference, Relation3.difference

This commit is contained in:
Mitchell Rosen 2021-10-06 18:41:08 -04:00
parent 023a86c585
commit 3a19e522b3
2 changed files with 30 additions and 11 deletions

View File

@ -9,6 +9,7 @@ module Unison.Util.Relation
fromManyRan,
fromMap,
fromMultimap,
fromSet,
unsafeFromMultimaps,
@ -75,6 +76,7 @@ module Unison.Util.Relation
-- ** Combinations
difference,
difference1,
intersection,
joinDom,
joinRan,
@ -149,12 +151,26 @@ unsafeFromMultimaps domain range =
-- * Functions about relations
-- | Compute the difference of two relations.
difference :: (Ord a, Ord b) => Relation a b -> Relation a b -> Relation a b
difference a b = fromList . S.toList $ diffSet
difference (Relation d1 r1) (Relation d2 r2) =
Relation
(Map.differenceWith setDifference1 d1 d2)
(Map.differenceWith setDifference1 r1 r2)
where
diffSet = S.difference seta setb
seta = S.fromList . toList $ a
setb = S.fromList . toList $ b
-- Set difference, but return Nothing if the difference is empty.
setDifference1 :: Ord a => Set a -> Set a -> Maybe (Set a)
setDifference1 xs ys =
if S.null zs then Nothing else Just zs
where
zs = S.difference xs ys
-- | Like 'difference', but returns @Nothing@ if the difference is empty.
difference1 :: (Ord a, Ord b) => Relation a b -> Relation a b -> Maybe (Relation a b)
difference1 xs ys =
if null zs then Nothing else Just zs
where
zs = difference xs ys
-- The size is calculated using the domain.
@ -373,6 +389,8 @@ filterManyDom r = filterDom (`manyDom` r) r
-- |
-- True if the relation @r@ is the 'empty' relation.
--
-- /O(1)/.
null :: Relation a b -> Bool
null r = M.null $ domain r

View File

@ -96,12 +96,13 @@ insertAll, deleteAll :: Foldable f => Ord a => Ord b => Ord c
insertAll f r = foldl' (\r x -> uncurry3 insert x r) r f
deleteAll f r = foldl' (\r x -> uncurry3 delete x r) r f
difference :: (Ord a, Ord b, Ord c)
=> Relation3 a b c
-> Relation3 a b c
-> Relation3 a b c
difference a b = deleteAll (Unison.Util.Relation3.toList b) a
-- | Compute the difference of two relations.
difference :: (Ord a, Ord b, Ord c) => Relation3 a b c -> Relation3 a b c -> Relation3 a b c
difference (Relation3 a1 b1 c1) (Relation3 a2 b2 c2) =
Relation3
(Map.differenceWith R.difference1 a1 a2)
(Map.differenceWith R.difference1 b1 b2)
(Map.differenceWith R.difference1 c1 c2)
delete a b c Relation3{..} =
Relation3