Skip to content
This repository was archived by the owner on Oct 4, 2020. It is now read-only.

Commit 3b53f89

Browse files
committed
Merge pull request #24 from hdgarrood/unionWith
add `unionWith`
2 parents ebc86a6 + e6c108e commit 3b53f89

File tree

3 files changed

+37
-2
lines changed

3 files changed

+37
-2
lines changed

README.md

+2
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@
5858

5959
union :: forall k v. (P.Ord k) => Map k v -> Map k v -> Map k v
6060

61+
unionWith :: forall k v. (P.Ord k) => (v -> v -> v) -> Map k v -> Map k v -> Map k v
62+
6163
unions :: forall k v. (P.Ord k) => [Map k v] -> Map k v
6264

6365
update :: forall k v. (P.Ord k) => (v -> Maybe v) -> k -> Map k v -> Map k v

src/Data/Map.purs

+9-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ module Data.Map
2222
keys,
2323
values,
2424
union,
25+
unionWith,
2526
unions,
2627
map,
2728
size
@@ -237,8 +238,15 @@ values Leaf = []
237238
values (Two left _ v right) = values left P.++ [v] P.++ values right
238239
values (Three left _ v1 mid _ v2 right) = values left P.++ [v1] P.++ values mid P.++ [v2] P.++ values right
239240

241+
-- Computes the union of two maps, except that when a key exists in both maps, its value in the result
242+
-- is computed by combining them with the supplied function.
243+
unionWith :: forall k v. (P.Ord k) => (v -> v -> v) -> Map k v -> Map k v -> Map k v
244+
unionWith f m1 m2 = foldl go m2 (toList m1)
245+
where
246+
go m (Tuple k v) = alter (Just P.<<< maybe v (f v)) k m
247+
240248
union :: forall k v. (P.Ord k) => Map k v -> Map k v -> Map k v
241-
union m1 m2 = foldl (\m (Tuple k v) -> insert k v m) m2 (toList m1)
249+
union = unionWith P.const
242250

243251
unions :: forall k v. (P.Ord k) => [Map k v] -> Map k v
244252
unions = foldl union empty

tests/Data/Map.purs

+26-1
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@ module Tests.Data.Map where
22

33
import Debug.Trace
44

5+
import Control.Alt ((<|>))
56
import Data.Maybe
67
import Data.Tuple
78
import Data.Array (map, length, nubBy)
89
import Data.Function (on)
9-
import Data.Foldable (foldl)
10+
import Data.Foldable (foldl, for_)
1011

1112
import Test.QuickCheck
1213

@@ -166,6 +167,30 @@ mapTests = do
166167
trace "Union is idempotent"
167168
quickCheck $ \m1 m2 -> (m1 `M.union` m2) == ((m1 `M.union` m2) `M.union` (m2 :: M.Map SmallKey Number))
168169

170+
trace "Union prefers left"
171+
quickCheck $ \m1 m2 k -> M.lookup k (M.union m1 (m2 :: M.Map SmallKey Number)) == (M.lookup k m1 <|> M.lookup k m2)
172+
173+
trace "unionWith"
174+
for_ [Tuple (+) 0, Tuple (*) 1] $ \(Tuple op ident) ->
175+
quickCheck $ \m1 m2 k ->
176+
let u = M.unionWith op m1 m2 :: M.Map SmallKey Number
177+
in case M.lookup k u of
178+
Nothing -> not (M.member k m1 || M.member k m2)
179+
Just v -> v == op (fromMaybe ident (M.lookup k m1)) (fromMaybe ident (M.lookup k m2))
180+
181+
trace "unionWith argument order"
182+
quickCheck $ \m1 m2 k ->
183+
let u = M.unionWith (-) m1 m2 :: M.Map SmallKey Number
184+
in1 = M.member k m1
185+
v1 = M.lookup k m1
186+
in2 = M.member k m2
187+
v2 = M.lookup k m2
188+
in case M.lookup k u of
189+
Just v | in1 && in2 -> Just v == ((-) <$> v1 <*> v2)
190+
Just v | in1 -> Just v == v1
191+
Just v -> Just v == v2
192+
Nothing -> not (in1 || in2)
193+
169194
trace "size"
170195
quickCheck $ \xs ->
171196
let xs' = nubBy ((==) `on` fst) xs

0 commit comments

Comments
 (0)