mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-16 18:42:30 +03:00
0e3beb028d
### Description There were several places in the codebase where we would either implement a generic container, or express the need for one. This PR extracts / creates all relevant containers, and adapts the relevant parts of the code to make use of said new generic containers. More specifically, it introduces the following modules: - `Data.Set.Extended`, for new functions on `Data.Set` - `Data.HashMap.Strict.Multi`, for hash maps that accept multiple values - `Data.HashMap.Strict.NonEmpty`, for hash maps that can never be constructed as empty - `Data.Trie`, for a generic implementation of a prefix tree This PR makes use of those new containers in the following parts of the code: - `Hasura.GraphQL.Execute.RemoteJoin.Types` - `Hasura.RQL.Types.Endpoint*` PR-URL: https://github.com/hasura/graphql-engine-mono/pull/3828 GitOrigin-RevId: e6c1b971bcb3f5ab66bc91d0fa4d0e9df7a0c6c6
93 lines
2.9 KiB
Haskell
93 lines
2.9 KiB
Haskell
-- | HashMap to multiple values.
|
|
module Data.HashMap.Strict.Multi
|
|
( -- * Type
|
|
MultiMap,
|
|
|
|
-- * Construction and conversions
|
|
singleton,
|
|
fromMap,
|
|
toMap,
|
|
fromList,
|
|
toList,
|
|
|
|
-- * Basic interface
|
|
lookup,
|
|
insert,
|
|
keys,
|
|
elems,
|
|
)
|
|
where
|
|
|
|
import Data.Aeson (ToJSON)
|
|
import Data.HashMap.Strict qualified as M
|
|
import Data.Hashable (Hashable)
|
|
import Data.Maybe (fromMaybe)
|
|
import Data.Set qualified as S
|
|
import Prelude hiding (lookup)
|
|
|
|
-------------------------------------------------------------------------------
|
|
|
|
-- | Map from keys to sets of values
|
|
newtype MultiMap k v = MultiMap
|
|
{ unMultiMap :: M.HashMap k (S.Set v)
|
|
}
|
|
deriving newtype (Eq, Show, ToJSON)
|
|
|
|
instance (Eq k, Hashable k, Ord v) => Semigroup (MultiMap k v) where
|
|
MultiMap m0 <> MultiMap m1 = MultiMap $ M.unionWith S.union m0 m1
|
|
|
|
instance (Eq k, Hashable k, Ord v) => Monoid (MultiMap k v) where
|
|
mempty = MultiMap mempty
|
|
|
|
-------------------------------------------------------------------------------
|
|
|
|
-- | Construct a 'MmultiMap' with a single key, to which only one
|
|
-- value is associated.
|
|
singleton :: Hashable k => k -> v -> MultiMap k v
|
|
singleton k v = MultiMap $ M.singleton k (S.singleton v)
|
|
|
|
-- | Construct a 'MultiMap' with the supplied mappings.
|
|
fromMap :: M.HashMap k (S.Set v) -> MultiMap k v
|
|
fromMap = MultiMap
|
|
|
|
-- | Convert a 'MultiMap' to a 'HashMap'.
|
|
toMap :: MultiMap k v -> M.HashMap k (S.Set v)
|
|
toMap = unMultiMap
|
|
|
|
-- | Creates a 'MultiMap' from an association list.
|
|
--
|
|
-- If the provided list constains duplicate mappings, the resulting
|
|
-- 'MultiMap' will store the set of all mapped values for each
|
|
-- duplicate key.
|
|
fromList :: (Eq k, Hashable k, Ord v) => [(k, v)] -> MultiMap k v
|
|
fromList l = MultiMap $ M.fromListWith (S.union) $ map (fmap S.singleton) l
|
|
|
|
-- | Creates an association list from a 'MultiMap'.
|
|
--
|
|
-- Each set of values associated with a given key is transformed back
|
|
-- into a list.
|
|
toList :: MultiMap k v -> [(k, [v])]
|
|
toList (MultiMap m) = M.toList $ fmap (S.toList) m
|
|
|
|
-------------------------------------------------------------------------------
|
|
|
|
-- | Return the value to which the specified key is mapped, or 'Nothing' if
|
|
-- this map contains no mapping for the key.
|
|
lookup :: (Eq k, Hashable k) => k -> MultiMap k v -> S.Set v
|
|
lookup k (MultiMap m) = fromMaybe S.empty $ M.lookup k m
|
|
|
|
-- | Associate the specified value with the specified key in this map.
|
|
--
|
|
-- If this map previously contained a mapping for the key, the new value is
|
|
-- inserted in the set, and does not replace the previous mapping.
|
|
insert :: (Eq k, Hashable k, Ord v) => k -> v -> MultiMap k v -> MultiMap k v
|
|
insert k v (MultiMap m) = MultiMap $ M.insertWith (S.union) k (S.singleton v) m
|
|
|
|
-- | Returns a list of this map's keys.
|
|
keys :: MultiMap k v -> [k]
|
|
keys = M.keys . unMultiMap
|
|
|
|
-- | Returns a list of this map's set of values.
|
|
elems :: MultiMap k v -> [S.Set v]
|
|
elems = M.elems . unMultiMap
|