|
6 | 6 | #ifdef STRICT |
7 | 7 | import Data.Map.Strict as Data.Map |
8 | 8 | import Data.Map.Merge.Strict |
| 9 | +import qualified Data.Map.Merge.Set.Strict as MergeSet |
9 | 10 | #else |
10 | 11 | import Data.Map.Lazy as Data.Map |
11 | 12 | import Data.Map.Merge.Lazy |
| 13 | +import qualified Data.Map.Merge.Set.Lazy as MergeSet |
12 | 14 | #endif |
13 | 15 | import Data.Map.Internal (Map, link2, link) |
14 | 16 | import Data.Map.Internal.Debug (showTree, showTreeWith, balanced) |
@@ -327,6 +329,8 @@ main = defaultMain $ testGroup "map-properties" |
327 | 329 | , testProperty "mapAccum" prop_mapAccum |
328 | 330 | , testProperty "mapAccumWithKey" prop_mapAccumWithKey |
329 | 331 | , testProperty "mapAccumRWithKey" prop_mapAccumRWithKey |
| 332 | + , testProperty "Merge.Set.merge" prop_mergeMapSet |
| 333 | + , testProperty "Merge.Set.mergeA" prop_mergeAMapSet |
330 | 334 | , testLaws $ Laws.eqLaws (Proxy :: Proxy (Map Int A)) |
331 | 335 | , testLaws $ Laws.ordLaws (Proxy :: Proxy (Map Int OrdA)) |
332 | 336 | , testLaws $ Laws.showLaws (Proxy :: Proxy (Map Int A)) |
@@ -1390,6 +1394,129 @@ instance (Arbitrary a, CoArbitrary a, Function a, CoArbitrary k, Function k) |
1390 | 1394 | , ZipWithMaybeMatched <$> arbitrary |
1391 | 1395 | ] |
1392 | 1396 |
|
| 1397 | +prop_mergeMapSet |
| 1398 | + :: WhenMissingSpec Int A |
| 1399 | + -> WhenMissingMapSetSpec Int A |
| 1400 | + -> WhenMatchedMapSetSpec Int A |
| 1401 | + -> Map Int A |
| 1402 | + -> Set Int |
| 1403 | + -> Property |
| 1404 | +prop_mergeMapSet miss1 miss2 match m1 s2 = |
| 1405 | + valid m .&&. |
| 1406 | + m === |
| 1407 | + (mapMaybeWithKey (\k x -> runIdentity (runWhenMissing miss1' k x)) m1Only `union` |
| 1408 | + mapMaybe id (fromSet (runIdentity . MergeSet.runWhenMissingSet miss2') s2Only) `union` |
| 1409 | + mapMaybeWithKey (\k x -> runIdentity (MergeSet.runWhenMatched match' k x)) m12Both) |
| 1410 | + where |
| 1411 | + miss1' = whenMissing miss1 |
| 1412 | + miss2' = whenMissingSet miss2 |
| 1413 | + match' = whenMatched match |
| 1414 | + |
| 1415 | + m = MergeSet.merge miss1' miss2' match' m1 s2 |
| 1416 | + |
| 1417 | + m1Only = filterKeys (`Set.notMember` s2) m1 |
| 1418 | + s2Only = Set.filter (`notMember` m1) s2 |
| 1419 | + m12Both = filterKeys (`Set.member` s2) m1 |
| 1420 | + |
| 1421 | + whenMissing spec = case spec of |
| 1422 | + DropMissing -> MergeSet.dropMissing |
| 1423 | + PreserveMissing -> MergeSet.preserveMissing |
| 1424 | + FilterMissing f -> MergeSet.filterMissing (applyFun2 f) |
| 1425 | + MapMissing f -> MergeSet.mapMissing (applyFun2 f) |
| 1426 | + MapMaybeMissing f -> MergeSet.mapMaybeMissing (applyFun2 f) |
| 1427 | + whenMissingSet spec = case spec of |
| 1428 | + DropMissingMapSet -> MergeSet.dropMissingSet |
| 1429 | + GenerateMissingMapSet f -> MergeSet.generateMissingSet (applyFun f) |
| 1430 | + GenerateMaybeMissingMapSet f -> MergeSet.generateMaybeMissingSet (applyFun f) |
| 1431 | + whenMatched spec = case spec of |
| 1432 | + FilterMatchedMapSet f -> MergeSet.filterMatched (applyFun2 f) |
| 1433 | + MapMatchedMapSet f -> MergeSet.mapMatched (applyFun2 f) |
| 1434 | + MapMaybeMatchedMapSet f -> MergeSet.mapMaybeMatched (applyFun2 f) |
| 1435 | + |
| 1436 | +-- This uses the instance |
| 1437 | +-- Monoid a => Applicative ((,) a) |
| 1438 | +-- to test that effects are sequenced in ascending key order. |
| 1439 | +prop_mergeAMapSet |
| 1440 | + :: WhenMissingSpec Int A |
| 1441 | + -> WhenMissingMapSetSpec Int A |
| 1442 | + -> WhenMatchedMapSetSpec Int A |
| 1443 | + -> Map Int A |
| 1444 | + -> Set Int |
| 1445 | + -> Property |
| 1446 | +prop_mergeAMapSet miss1 miss2 match m1 s2 = |
| 1447 | + valid m .&&. |
| 1448 | + m === |
| 1449 | + (mapMaybeWithKey (\k x -> snd (runWhenMissing miss1' k x)) m1Only `union` |
| 1450 | + mapMaybe id (fromSet (snd . MergeSet.runWhenMissingSet miss2') s2Only) `union` |
| 1451 | + mapMaybeWithKey (\k x -> snd (MergeSet.runWhenMatched match' k x)) m12Both) .&&. |
| 1452 | + ks === |
| 1453 | + sort |
| 1454 | + (concat |
| 1455 | + (fmap (\(k,x) -> fst (runWhenMissing miss1' k x)) (toList m1Only) ++ |
| 1456 | + fmap (fst . MergeSet.runWhenMissingSet miss2') (Set.toList s2Only) ++ |
| 1457 | + fmap (\(k,x) -> fst (MergeSet.runWhenMatched match' k x)) (toList m12Both))) |
| 1458 | + where |
| 1459 | + miss1' = whenMissing miss1 |
| 1460 | + miss2' = whenMissingSet miss2 |
| 1461 | + match' = whenMatched match |
| 1462 | + |
| 1463 | + (ks, m) = MergeSet.mergeA miss1' miss2' match' m1 s2 |
| 1464 | + |
| 1465 | + m1Only = filterKeys (`Set.notMember` s2) m1 |
| 1466 | + s2Only = Set.filter (`notMember` m1) s2 |
| 1467 | + m12Both = filterKeys (`Set.member` s2) m1 |
| 1468 | + |
| 1469 | + whenMissing spec = case spec of |
| 1470 | + DropMissing -> MergeSet.dropMissing |
| 1471 | + PreserveMissing -> MergeSet.preserveMissing |
| 1472 | + FilterMissing f -> MergeSet.filterAMissing (\k x -> ([k], applyFun2 f k x)) |
| 1473 | + MapMissing f -> MergeSet.traverseMissing (\k x -> ([k], applyFun2 f k x)) |
| 1474 | + MapMaybeMissing f -> MergeSet.traverseMaybeMissing (\k x -> ([k], applyFun2 f k x)) |
| 1475 | + whenMissingSet spec = case spec of |
| 1476 | + DropMissingMapSet -> MergeSet.dropMissingSet |
| 1477 | + GenerateMissingMapSet f -> MergeSet.generateAMissingSet (\k -> ([k], applyFun f k)) |
| 1478 | + GenerateMaybeMissingMapSet f -> MergeSet.generateMaybeAMissingSet (\k -> ([k], applyFun f k)) |
| 1479 | + whenMatched spec = case spec of |
| 1480 | + FilterMatchedMapSet f -> MergeSet.filterAMatched (\k x -> ([k], applyFun2 f k x)) |
| 1481 | + MapMatchedMapSet f -> MergeSet.traverseMatched (\k x -> ([k], applyFun2 f k x)) |
| 1482 | + MapMaybeMatchedMapSet f -> MergeSet.traverseMaybeMatched (\k x -> ([k], applyFun2 f k x)) |
| 1483 | + |
| 1484 | +data WhenMissingMapSetSpec k a |
| 1485 | + = DropMissingMapSet |
| 1486 | + | GenerateMissingMapSet (Fun k a) |
| 1487 | + | GenerateMaybeMissingMapSet (Fun k (Maybe a)) |
| 1488 | + deriving Show |
| 1489 | + |
| 1490 | +instance (Arbitrary a, CoArbitrary a, Function a, CoArbitrary k, Function k) |
| 1491 | + => Arbitrary (WhenMissingMapSetSpec k a) where |
| 1492 | + arbitrary = oneof |
| 1493 | + [ pure DropMissingMapSet |
| 1494 | + , GenerateMissingMapSet <$> arbitrary |
| 1495 | + , GenerateMaybeMissingMapSet <$> arbitrary |
| 1496 | + ] |
| 1497 | + shrink spec = case spec of |
| 1498 | + DropMissingMapSet -> [] |
| 1499 | + GenerateMissingMapSet f -> GenerateMissingMapSet <$> shrink f |
| 1500 | + GenerateMaybeMissingMapSet f -> GenerateMaybeMissingMapSet <$> shrink f |
| 1501 | + |
| 1502 | +data WhenMatchedMapSetSpec k a |
| 1503 | + = FilterMatchedMapSet (Fun (k, a) Bool) |
| 1504 | + | MapMatchedMapSet (Fun (k, a) a) |
| 1505 | + | MapMaybeMatchedMapSet (Fun (k, a) (Maybe a)) |
| 1506 | + deriving Show |
| 1507 | + |
| 1508 | +instance (Arbitrary a, CoArbitrary a, Function a, CoArbitrary k, Function k) |
| 1509 | + => Arbitrary (WhenMatchedMapSetSpec k a) where |
| 1510 | + arbitrary = oneof |
| 1511 | + [ FilterMatchedMapSet <$> arbitrary |
| 1512 | + , MapMatchedMapSet <$> arbitrary |
| 1513 | + , MapMaybeMatchedMapSet <$> arbitrary |
| 1514 | + ] |
| 1515 | + shrink spec = case spec of |
| 1516 | + FilterMatchedMapSet f -> FilterMatchedMapSet <$> shrink f |
| 1517 | + MapMatchedMapSet f -> MapMatchedMapSet <$> shrink f |
| 1518 | + MapMaybeMatchedMapSet f -> MapMaybeMatchedMapSet <$> shrink f |
| 1519 | + |
1393 | 1520 | ---------------------------------------------------------------- |
1394 | 1521 |
|
1395 | 1522 | prop_list :: [Int] -> Bool |
|
0 commit comments