/compiler/GHC/Types/Unique/DSet.hs

https://github.com/bgamari/ghc · Haskell · 142 lines · 86 code · 35 blank · 21 comment · 1 complexity · 36f4c69c6e7939741c6f16ae9ac63c1d MD5 · raw file

  1. -- (c) Bartosz Nitka, Facebook, 2015
  2. -- |
  3. -- Specialised deterministic sets, for things with @Uniques@
  4. --
  5. -- Based on 'UniqDFM's (as you would expect).
  6. -- See Note [Deterministic UniqFM] in "GHC.Types.Unique.DFM" for explanation why we need it.
  7. --
  8. -- Basically, the things need to be in class 'Uniquable'.
  9. {-# LANGUAGE DeriveDataTypeable #-}
  10. module GHC.Types.Unique.DSet (
  11. -- * Unique set type
  12. UniqDSet, -- type synonym for UniqFM a
  13. getUniqDSet,
  14. pprUniqDSet,
  15. -- ** Manipulating these sets
  16. delOneFromUniqDSet, delListFromUniqDSet,
  17. emptyUniqDSet,
  18. unitUniqDSet,
  19. mkUniqDSet,
  20. addOneToUniqDSet, addListToUniqDSet,
  21. unionUniqDSets, unionManyUniqDSets,
  22. minusUniqDSet, uniqDSetMinusUniqSet,
  23. intersectUniqDSets, uniqDSetIntersectUniqSet,
  24. nonDetStrictFoldUniqDSet,
  25. elementOfUniqDSet,
  26. filterUniqDSet,
  27. sizeUniqDSet,
  28. isEmptyUniqDSet,
  29. lookupUniqDSet,
  30. uniqDSetToList,
  31. partitionUniqDSet,
  32. mapUniqDSet
  33. ) where
  34. import GHC.Prelude
  35. import GHC.Utils.Outputable
  36. import GHC.Types.Unique.DFM
  37. import GHC.Types.Unique.Set
  38. import GHC.Types.Unique
  39. import Data.Coerce
  40. import Data.Data
  41. -- See Note [UniqSet invariant] in GHC.Types.Unique.Set for why we want a newtype here.
  42. -- Beyond preserving invariants, we may also want to 'override' typeclass
  43. -- instances.
  44. newtype UniqDSet a = UniqDSet {getUniqDSet' :: UniqDFM a a}
  45. deriving (Data)
  46. emptyUniqDSet :: UniqDSet a
  47. emptyUniqDSet = UniqDSet emptyUDFM
  48. unitUniqDSet :: Uniquable a => a -> UniqDSet a
  49. unitUniqDSet x = UniqDSet (unitUDFM x x)
  50. mkUniqDSet :: Uniquable a => [a] -> UniqDSet a
  51. mkUniqDSet = foldl' addOneToUniqDSet emptyUniqDSet
  52. -- The new element always goes to the right of existing ones.
  53. addOneToUniqDSet :: Uniquable a => UniqDSet a -> a -> UniqDSet a
  54. addOneToUniqDSet (UniqDSet set) x = UniqDSet (addToUDFM set x x)
  55. addListToUniqDSet :: Uniquable a => UniqDSet a -> [a] -> UniqDSet a
  56. addListToUniqDSet = foldl' addOneToUniqDSet
  57. delOneFromUniqDSet :: Uniquable a => UniqDSet a -> a -> UniqDSet a
  58. delOneFromUniqDSet (UniqDSet s) = UniqDSet . delFromUDFM s
  59. delListFromUniqDSet :: Uniquable a => UniqDSet a -> [a] -> UniqDSet a
  60. delListFromUniqDSet (UniqDSet s) = UniqDSet . delListFromUDFM s
  61. unionUniqDSets :: UniqDSet a -> UniqDSet a -> UniqDSet a
  62. unionUniqDSets (UniqDSet s) (UniqDSet t) = UniqDSet (plusUDFM s t)
  63. unionManyUniqDSets :: [UniqDSet a] -> UniqDSet a
  64. unionManyUniqDSets [] = emptyUniqDSet
  65. unionManyUniqDSets (x:xs) = foldl' unionUniqDSets x xs
  66. minusUniqDSet :: UniqDSet a -> UniqDSet a -> UniqDSet a
  67. minusUniqDSet (UniqDSet s) (UniqDSet t) = UniqDSet (minusUDFM s t)
  68. uniqDSetMinusUniqSet :: UniqDSet a -> UniqSet a -> UniqDSet a
  69. uniqDSetMinusUniqSet xs ys
  70. = UniqDSet (udfmMinusUFM (getUniqDSet xs) (getUniqSet ys))
  71. intersectUniqDSets :: UniqDSet a -> UniqDSet a -> UniqDSet a
  72. intersectUniqDSets (UniqDSet s) (UniqDSet t) = UniqDSet (intersectUDFM s t)
  73. uniqDSetIntersectUniqSet :: UniqDSet a -> UniqSet a -> UniqDSet a
  74. uniqDSetIntersectUniqSet xs ys
  75. = UniqDSet (udfmIntersectUFM (getUniqDSet xs) (getUniqSet ys))
  76. -- See Note [Deterministic UniqFM] to learn about nondeterminism.
  77. -- If you use this please provide a justification why it doesn't introduce
  78. -- nondeterminism.
  79. nonDetStrictFoldUniqDSet :: (a -> b -> b) -> b -> UniqDSet a -> b
  80. nonDetStrictFoldUniqDSet f acc (UniqDSet s) = nonDetStrictFoldUDFM f acc s
  81. elementOfUniqDSet :: Uniquable a => a -> UniqDSet a -> Bool
  82. elementOfUniqDSet k = elemUDFM k . getUniqDSet
  83. filterUniqDSet :: (a -> Bool) -> UniqDSet a -> UniqDSet a
  84. filterUniqDSet p (UniqDSet s) = UniqDSet (filterUDFM p s)
  85. sizeUniqDSet :: UniqDSet a -> Int
  86. sizeUniqDSet = sizeUDFM . getUniqDSet
  87. isEmptyUniqDSet :: UniqDSet a -> Bool
  88. isEmptyUniqDSet = isNullUDFM . getUniqDSet
  89. lookupUniqDSet :: Uniquable a => UniqDSet a -> a -> Maybe a
  90. lookupUniqDSet = lookupUDFM . getUniqDSet
  91. uniqDSetToList :: UniqDSet a -> [a]
  92. uniqDSetToList = eltsUDFM . getUniqDSet
  93. partitionUniqDSet :: (a -> Bool) -> UniqDSet a -> (UniqDSet a, UniqDSet a)
  94. partitionUniqDSet p = coerce . partitionUDFM p . getUniqDSet
  95. -- See Note [UniqSet invariant] in GHC.Types.Unique.Set
  96. mapUniqDSet :: Uniquable b => (a -> b) -> UniqDSet a -> UniqDSet b
  97. mapUniqDSet f = mkUniqDSet . map f . uniqDSetToList
  98. -- Two 'UniqDSet's are considered equal if they contain the same
  99. -- uniques.
  100. instance Eq (UniqDSet a) where
  101. UniqDSet a == UniqDSet b = equalKeysUDFM a b
  102. getUniqDSet :: UniqDSet a -> UniqDFM a a
  103. getUniqDSet = getUniqDSet'
  104. instance Outputable a => Outputable (UniqDSet a) where
  105. ppr = pprUniqDSet ppr
  106. pprUniqDSet :: (a -> SDoc) -> UniqDSet a -> SDoc
  107. pprUniqDSet f = braces . pprWithCommas f . uniqDSetToList