@@ -21,6 +21,8 @@ module Data.TypeRep.CacheMap
2121 , insert
2222 , delete
2323 , hoist
24+ , unionWith
25+ , union
2426 , lookup
2527 , member
2628 , size
@@ -51,6 +53,7 @@ import GHC.Word (Word64 (..))
5153import Unsafe.Coerce (unsafeCoerce)
5254
5355import qualified Data.IntMap.Strict as IM
56+import qualified Data.Map.Strict as Map
5457import qualified GHC.Exts as GHC (fromList, toList)
5558
5659-- | Map-like data structure that keeps types as keys.
@@ -123,6 +126,25 @@ Just "a"
123126-}
124127hoist :: (forall x. f x -> g x) -> TypeRepMap f -> TypeRepMap g
125128hoist f (TypeRepMap as bs ans) = TypeRepMap as bs $ mapArray' (toAny . f . fromAny) ans
129+{-# INLINE hoist #-}
130+
131+-- | The union with a combining function.
132+unionWith :: (forall x. f x -> f x -> f x) -> TypeRepMap f -> TypeRepMap f -> TypeRepMap f
133+unionWith f m1 m2 = fromListPairs
134+ $ Map.toList
135+ $ Map.unionWith combine
136+ (Map.fromList $ toPairList m1)
137+ (Map.fromList $ toPairList m2)
138+ where
139+ combine :: Any -> Any -> Any
140+ combine a b = toAny $ f (fromAny a) (fromAny b)
141+{-# INLINE unionWith #-}
142+
143+-- | The (left-biased) union of two maps. It prefers the first map when
144+-- duplicate keys are encountered, i.e. @'union' == 'unionWith' const@.
145+union :: TypeRepMap f -> TypeRepMap f -> TypeRepMap f
146+union = unionWith const
147+{-# INLINE union #-}
126148
127149{- | Returns 'True' if there exist value of given type.
128150