Skip to content

Commit fb2aa39

Browse files
authored
Adjust from{Asc,Desc}List* for strict maps (#1023)
Make the functions strict in the first value in runs of entries with equal keys. This makes the strictness match that of the corresponding fromList functions.
1 parent 734785d commit fb2aa39

File tree

3 files changed

+61
-39
lines changed

3 files changed

+61
-39
lines changed

containers/changelog.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,22 @@
99
`Data.IntSet.splitMember` are now strict in the key. Previously, the key was
1010
ignored for an empty map or set. (Soumik Sarkar)
1111

12+
* The following functions have been updated to match the strictness of their
13+
`fromList` counterparts:
14+
15+
* `Data.Map.Strict.fromAscList`
16+
* `Data.Map.Strict.fromAscListWith`
17+
* `Data.Map.Strict.fromAscListWithKey`
18+
* `Data.Map.Strict.fromDescList`
19+
* `Data.Map.Strict.fromDescListWith`
20+
* `Data.Map.Strict.fromDescListWithKey`
21+
* `Data.IntMap.Strict.fromAscList`
22+
* `Data.IntMap.Strict.fromAscListWith`
23+
* `Data.IntMap.Strict.fromAscListWithKey`
24+
25+
Previously they were lazier and did not force the first value in runs of at
26+
least 2 entries with equal keys. (Soumik Sarkar)
27+
1228
### Bug fixes
1329

1430
* `Data.Map.Strict.mergeWithKey` now forces the result of the combining function

containers/src/Data/IntMap/Strict/Internal.hs

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1203,15 +1203,18 @@ fromMonoListWithKey distinct f = go
12031203

12041204
-- `addAll'` collects all keys equal to `kx` into a single value,
12051205
-- and then proceeds with `addAll`.
1206-
addAll' !kx vx []
1207-
= Tip kx $! vx
1208-
addAll' !kx vx ((ky,vy) : zs)
1206+
--
1207+
-- We want to have the same strictness as fromListWithKey, which is achieved
1208+
-- with the bang on vx.
1209+
addAll' !kx !vx []
1210+
= Tip kx vx
1211+
addAll' !kx !vx ((ky,vy) : zs)
12091212
| Nondistinct <- distinct, kx == ky
1210-
= let !v = f kx vy vx in addAll' ky v zs
1211-
-- inlined: | otherwise = addAll kx (Tip kx $! vx) (ky : zs)
1213+
= addAll' ky (f kx vy vx) zs
1214+
-- inlined: | otherwise = addAll kx (Tip kx vx) (ky : zs)
12121215
| m <- branchMask kx ky
12131216
, Inserted ty zs' <- addMany' m ky vy zs
1214-
= addAll kx (linkWithMask m ky ty kx (Tip kx $! vx)) zs'
1217+
= addAll kx (linkWithMask m ky ty kx (Tip kx vx)) zs'
12151218

12161219
-- for `addAll` and `addMany`, kx is /a/ key inside the tree `tx`
12171220
-- `addAll` consumes the rest of the list, adding to the tree `tx`
@@ -1223,17 +1226,20 @@ fromMonoListWithKey distinct f = go
12231226
= addAll kx (linkWithMask m ky ty kx tx) zs'
12241227

12251228
-- `addMany'` is similar to `addAll'`, but proceeds with `addMany'`.
1226-
addMany' !_m !kx vx []
1227-
= Inserted (Tip kx $! vx) []
1228-
addMany' !m !kx vx zs0@((ky,vy) : zs)
1229+
--
1230+
-- We want to have the same strictness as fromListWithKey, which is achieved
1231+
-- with the bang on vx.
1232+
addMany' !_m !kx !vx []
1233+
= Inserted (Tip kx vx) []
1234+
addMany' !m !kx !vx zs0@((ky,vy) : zs)
12291235
| Nondistinct <- distinct, kx == ky
1230-
= let !v = f kx vy vx in addMany' m ky v zs
1231-
-- inlined: | otherwise = addMany m kx (Tip kx $! vx) (ky : zs)
1236+
= addMany' m ky (f kx vy vx) zs
1237+
-- inlined: | otherwise = addMany m kx (Tip kx vx) (ky : zs)
12321238
| mask kx m /= mask ky m
1233-
= Inserted (Tip kx $! vx) zs0
1239+
= Inserted (Tip kx vx) zs0
12341240
| mxy <- branchMask kx ky
12351241
, Inserted ty zs' <- addMany' mxy ky vy zs
1236-
= addMany m kx (linkWithMask mxy ky ty kx (Tip kx $! vx)) zs'
1242+
= addMany m kx (linkWithMask mxy ky ty kx (Tip kx vx)) zs'
12371243

12381244
-- `addAll` adds to `tx` all keys whose prefix w.r.t. `m` agrees with `kx`.
12391245
addMany !_m !_kx tx []

containers/src/Data/Map/Strict/Internal.hs

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1678,20 +1678,20 @@ fromDescListWith f xs
16781678
-- Also see the performance note on 'fromListWith'.
16791679

16801680
fromAscListWithKey :: Eq k => (k -> a -> a -> a) -> [(k,a)] -> Map k a
1681-
fromAscListWithKey f xs
1682-
= fromDistinctAscList (combineEq f xs)
1681+
fromAscListWithKey f xs0 = fromDistinctAscList xs1
16831682
where
1684-
-- [combineEq f xs] combines equal elements with function [f] in an ordered list [xs]
1685-
combineEq _ xs'
1686-
= case xs' of
1687-
[] -> []
1688-
[x] -> [x]
1689-
(x:xx) -> combineEq' x xx
1690-
1691-
combineEq' z [] = [z]
1692-
combineEq' z@(kz,zz) (x@(kx,xx):xs')
1693-
| kx==kz = let yy = f kx xx zz in yy `seq` combineEq' (kx,yy) xs'
1694-
| otherwise = z:combineEq' x xs'
1683+
xs1 = case xs0 of
1684+
[] -> []
1685+
[x] -> [x]
1686+
x:xs -> combineEq x xs
1687+
1688+
-- We want to have the same strictness as fromListWithKey, which is achieved
1689+
-- with the bang on yy.
1690+
combineEq y@(ky, !yy) xs = case xs of
1691+
[] -> [y]
1692+
x@(kx, xx) : xs'
1693+
| kx == ky -> combineEq (kx, f kx xx yy) xs'
1694+
| otherwise -> y : combineEq x xs'
16951695
#if __GLASGOW_HASKELL__
16961696
{-# INLINABLE fromAscListWithKey #-}
16971697
#endif
@@ -1708,20 +1708,20 @@ fromAscListWithKey f xs
17081708
-- Also see the performance note on 'fromListWith'.
17091709

17101710
fromDescListWithKey :: Eq k => (k -> a -> a -> a) -> [(k,a)] -> Map k a
1711-
fromDescListWithKey f xs
1712-
= fromDistinctDescList (combineEq f xs)
1711+
fromDescListWithKey f xs0 = fromDistinctDescList xs1
17131712
where
1714-
-- [combineEq f xs] combines equal elements with function [f] in an ordered list [xs]
1715-
combineEq _ xs'
1716-
= case xs' of
1717-
[] -> []
1718-
[x] -> [x]
1719-
(x:xx) -> combineEq' x xx
1720-
1721-
combineEq' z [] = [z]
1722-
combineEq' z@(kz,zz) (x@(kx,xx):xs')
1723-
| kx==kz = let yy = f kx xx zz in yy `seq` combineEq' (kx,yy) xs'
1724-
| otherwise = z:combineEq' x xs'
1713+
xs1 = case xs0 of
1714+
[] -> []
1715+
[x] -> [x]
1716+
x:xs -> combineEq x xs
1717+
1718+
-- We want to have the same strictness as fromListWithKey, which is achieved
1719+
-- with the bang on yy.
1720+
combineEq y@(ky, !yy) xs = case xs of
1721+
[] -> [y]
1722+
x@(kx, xx) : xs'
1723+
| kx == ky -> combineEq (kx, f kx xx yy) xs'
1724+
| otherwise -> y : combineEq x xs'
17251725
#if __GLASGOW_HASKELL__
17261726
{-# INLINABLE fromDescListWithKey #-}
17271727
#endif

0 commit comments

Comments
 (0)