diff --git a/src/Data/Map.purs b/src/Data/Map.purs index e764370b..798ef32a 100644 --- a/src/Data/Map.purs +++ b/src/Data/Map.purs @@ -32,6 +32,7 @@ module Data.Map , union , unionWith , unions + , unionsWith , isSubmap , size , mapWithKey @@ -608,6 +609,9 @@ union = unionWith const unions :: forall k v f. Ord k => Foldable f => f (Map k v) -> Map k v unions = foldl union empty +unionsWith :: forall k v f. Ord k => Foldable f => (v -> v -> v) -> f (Map k v) -> Map k v +unionsWith f = foldl (unionWith f) empty + -- | Test whether one map contains all of the keys and values contained in another map isSubmap :: forall k v. Ord k => Eq v => Map k v -> Map k v -> Boolean isSubmap m1 m2 = LL.all f $ (toUnfoldable m1 :: LL.List (Tuple k v)) diff --git a/test/Test/Data/Map.purs b/test/Test/Data/Map.purs index bc38e615..e53f81aa 100644 --- a/test/Test/Data/Map.purs +++ b/test/Test/Data/Map.purs @@ -23,6 +23,9 @@ import Test.QuickCheck.Gen (elements, oneOf) newtype TestMap k v = TestMap (M.Map k v) +unwrap :: forall k v. TestMap k v -> M.Map k v +unwrap (TestMap m) = m + instance arbTestMap :: (Eq k, Ord k, Arbitrary k, Arbitrary v) => Arbitrary (TestMap k v) where arbitrary = TestMap <$> genMap arbitrary arbitrary @@ -214,6 +217,26 @@ mapTests = do Just v -> Just v == v2 Nothing -> not (in1 || in2) + log "unionsWith" + for_ [Tuple (+) 0, Tuple (*) 1] $ \(Tuple op ident) -> + quickCheck $ \(testMaps :: Array (TestMap SmallKey Int)) k -> + let testMaps' = unwrap <$> testMaps + u = M.unionsWith op testMaps' + in case M.lookup k u of + Nothing -> A.all (not <<< M.member k) testMaps' + Just v -> (v == _) <<< A.foldl op ident <<< map (fromMaybe ident <<< M.lookup k) $ testMaps' + + log "unionsWith argument order" + quickCheck $ \(testMaps :: Array (TestMap SmallKey Int)) k -> + let testMaps' = unwrap <$> testMaps + u = M.unionsWith (-) testMaps' + in case M.lookup k u of + Just v -> + case A.uncons <<< A.mapMaybe (M.lookup k) $ testMaps' of + Nothing -> false + Just { head, tail } -> v == foldl (-) head tail + Nothing -> A.all (not <<< M.member k) testMaps' + log "size" quickCheck $ \xs -> let xs' = nubBy ((==) `on` fst) xs