Skip to content

Commit 55ad298

Browse files
committed
Change IntMap.lookup and IntMap.find and add new IntMap.query
- `IntMap.lookup` and `IntMap.find` no longer check for short circuit failure. - Add a new function `IntMap.query` with the old fast-fail behaviour.
1 parent ff3d6af commit 55ad298

File tree

6 files changed

+88
-13
lines changed

6 files changed

+88
-13
lines changed

containers-tests/benchmarks/IntMap.hs

+36-4
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,23 @@ import Data.Maybe (fromMaybe)
1111
import Prelude hiding (lookup)
1212

1313
main = do
14-
let m = M.fromAscList elems :: M.IntMap Int
15-
evaluate $ rnf [m]
14+
let m = M.fromAscList elems_hits :: M.IntMap Int
15+
let m' = M.fromAscList elems_mid :: M.IntMap Int
16+
let m'' = M.fromAscList elems_most :: M.IntMap Int
17+
let m''' = M.fromAscList elems_misses :: M.IntMap Int
18+
let m'''' = M.fromAscList elems_mixed :: M.IntMap Int
19+
evaluate $ rnf [m, m', m'', m''', m'''']
1620
defaultMain
17-
[ bench "lookup" $ whnf (lookup keys) m
21+
[ bench "query_hits" $ whnf (query keys) m
22+
, bench "query_half" $ whnf (query keys) m'
23+
, bench "query_most" $ whnf (query keys) m''
24+
, bench "query_misses" $ whnf (query keys'') m'''
25+
, bench "query_mixed" $ whnf (query keys) m''''
26+
, bench "lookup_hits" $ whnf (lookup keys) m
27+
, bench "lookup_half" $ whnf (lookup keys) m'
28+
, bench "lookup_most" $ whnf (lookup keys) m''
29+
, bench "lookup_misses" $ whnf (lookup keys'') m'''
30+
, bench "lookup_mixed" $ whnf (lookup keys) m''''
1831
, bench "insert" $ whnf (ins elems) M.empty
1932
, bench "insertWith empty" $ whnf (insWith elems) M.empty
2033
, bench "insertWith update" $ whnf (insWith elems) m
@@ -44,19 +57,33 @@ main = do
4457
(M.fromList $ zip [1..10] [1..10])
4558
]
4659
where
47-
elems = zip keys values
60+
elems = elems_hits
61+
elems_hits = zip keys values
62+
elems_mid = zip (map (+ (2^12 `div` 2)) keys) values
63+
elems_most = zip (map (+ (2^12 `div` 10)) keys) values
64+
elems_misses = zip (map (\x-> x * 2 + 1) keys) values
65+
elems_mixed = zip mixedKeys values
66+
--------------------------------------------------------
4867
keys = [1..2^12]
68+
keys' = fmap (+ 1000000) keys
69+
keys'' = fmap (* 2) [1..2^12]
70+
mixedKeys = interleave keys keys'
4971
values = [1..2^12]
72+
--------------------------------------------------------
5073
sum k v1 v2 = k + v1 + v2
5174
consPair k v xs = (k, v) : xs
5275

76+
------------------------------------------------------------
5377
add3 :: Int -> Int -> Int -> Int
5478
add3 x y z = x + y + z
5579
{-# INLINE add3 #-}
5680

5781
lookup :: [Int] -> M.IntMap Int -> Int
5882
lookup xs m = foldl' (\n k -> fromMaybe n (M.lookup k m)) 0 xs
5983

84+
query :: [Int] -> M.IntMap Int -> Int
85+
query xs m = foldl' (\n k -> fromMaybe n (M.query k m)) 0 xs
86+
6087
ins :: [(Int, Int)] -> M.IntMap Int -> M.IntMap Int
6188
ins xs m = foldl' (\m (k, v) -> M.insert k v m) m xs
6289

@@ -95,3 +122,8 @@ alt xs m = foldl' (\m k -> M.alter id k m) m xs
95122
maybeDel :: Int -> Maybe Int
96123
maybeDel n | n `mod` 3 == 0 = Nothing
97124
| otherwise = Just n
125+
126+
------------------------------------------------------------
127+
interleave :: [Int] -> [Int] -> [Int]
128+
interleave [] ys = ys
129+
interleave (x:xs) (y:ys) = x : y : interleave xs ys

containers-tests/tests/intmap-properties.hs

+30-5
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ main = defaultMain $ testGroup "intmap-properties"
4545
, testCase "member" test_member
4646
, testCase "notMember" test_notMember
4747
, testCase "lookup" test_lookup
48+
, testCase "query " test_query
4849
, testCase "findWithDefault" test_findWithDefault
4950
, testCase "lookupLT" test_lookupLT
5051
, testCase "lookupGT" test_lookupGT
@@ -295,18 +296,42 @@ test_notMember = do
295296

296297
test_lookup :: Assertion
297298
test_lookup = do
298-
employeeCurrency 1 @?= Just 1
299-
employeeCurrency 2 @?= Nothing
299+
employeeCurrency 1 @?= Just 1
300+
employeeCurrency 2 @?= Just 2
301+
employeeCurrency 3 @?= Just 3
302+
employeeCurrency 4 @?= Just 4
303+
employeeCurrency 5 @?= Nothing
304+
employeeCurrency (2^10) @?= Just 42
305+
employeeCurrency 6 @?= Nothing
300306
where
301-
employeeDept = fromList([(1,2), (3,1)])
302-
deptCountry = fromList([(1,1), (2,2)])
303-
countryCurrency = fromList([(1, 2), (2, 1)])
307+
employeeDept = fromList [(1,2), (2, 14), (3, 10), (4, 18), (2^10, 100)]
308+
deptCountry = fromList [(1,1), (14, 14), (10, 10), (18, 18), (100, 100), (2,2)]
309+
countryCurrency = fromList [(1, 2), (2, 1), (14, 2), (10, 3), (18, 4), (100, 42)]
304310
employeeCurrency :: Int -> Maybe Int
305311
employeeCurrency name = do
306312
dept <- lookup name employeeDept
307313
country <- lookup dept deptCountry
308314
lookup country countryCurrency
309315

316+
test_query :: Assertion
317+
test_query = do
318+
employeeCurrency 1 @?= Just 1
319+
employeeCurrency 2 @?= Just 2
320+
employeeCurrency 3 @?= Just 3
321+
employeeCurrency 4 @?= Just 4
322+
employeeCurrency 5 @?= Nothing
323+
employeeCurrency (2^10) @?= Just 42
324+
employeeCurrency 6 @?= Nothing
325+
where
326+
employeeDept = fromList [(1,2), (2, 14), (3, 10), (4, 18), (2^10, 100)]
327+
deptCountry = fromList [(1,1), (14, 14), (10, 10), (18, 18), (100, 100), (2,2)]
328+
countryCurrency = fromList [(1, 2), (2, 1), (14, 2), (10, 3), (18, 4), (100, 42)]
329+
employeeCurrency :: Int -> Maybe Int
330+
employeeCurrency name = do
331+
dept <- query name employeeDept
332+
country <- query dept deptCountry
333+
query country countryCurrency
334+
310335
test_findWithDefault :: Assertion
311336
test_findWithDefault = do
312337
findWithDefault 'x' 1 (fromList [(5,'a'), (3,'b')]) @?= 'x'

containers/src/Data/IntMap/Internal.hs

+18-4
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ module Data.IntMap.Internal (
8686
, member
8787
, notMember
8888
, lookup
89+
, query
8990
, findWithDefault
9091
, lookupLT
9192
, lookupGT
@@ -594,9 +595,23 @@ notMember k m = not $ member k m
594595

595596
-- | /O(min(n,W))/. Lookup the value at a key in the map. See also 'Data.Map.lookup'.
596597

597-
-- See Note: Local 'go' functions and capturing]
598+
-- See Note: Local 'go' functions and capturing
598599
lookup :: Key -> IntMap a -> Maybe a
599600
lookup !k = go
601+
where
602+
go (Bin _p m l r) | zero k m = go l
603+
| otherwise = go r
604+
go (Tip kx x) | k == kx = Just x
605+
| otherwise = Nothing
606+
go Nil = Nothing
607+
608+
-- | /O(min(n,W))/. 'query' has identical behaviour to 'Data.IntMap.Internal.lookup', but
609+
-- will fail faster if the key is not present. When the key is (likely) present, it is
610+
-- preferable to use 'Data.IntMap.Internal.lookup' instead.
611+
612+
-- See Note: Local 'go' functions and capturing
613+
query :: Key -> IntMap a -> Maybe a
614+
query !k = go
600615
where
601616
go (Bin p m l r) | nomatch k p m = Nothing
602617
| zero k m = go l
@@ -610,9 +625,8 @@ lookup !k = go
610625
find :: Key -> IntMap a -> a
611626
find !k = go
612627
where
613-
go (Bin p m l r) | nomatch k p m = not_found
614-
| zero k m = go l
615-
| otherwise = go r
628+
go (Bin _p m l r) | zero k m = go l
629+
| otherwise = go r
616630
go (Tip kx x) | k == kx = x
617631
| otherwise = not_found
618632
go Nil = not_found

containers/src/Data/IntMap/Lazy.hs

+1
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ module Data.IntMap.Lazy (
108108
-- * Query
109109
-- ** Lookup
110110
, IM.lookup
111+
, IM.query
111112
, (!?)
112113
, (!)
113114
, findWithDefault

containers/src/Data/IntMap/Strict.hs

+1
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ module Data.IntMap.Strict (
127127
-- * Query
128128
-- ** Lookup
129129
, lookup
130+
, query
130131
, (!?)
131132
, (!)
132133
, findWithDefault

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

+2
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ module Data.IntMap.Strict.Internal (
127127
-- * Query
128128
-- ** Lookup
129129
, lookup
130+
, query
130131
, (!?)
131132
, (!)
132133
, findWithDefault
@@ -327,6 +328,7 @@ import Data.IntMap.Internal
327328
, null
328329
, partition
329330
, partitionWithKey
331+
, query
330332
, restrictKeys
331333
, size
332334
, split

0 commit comments

Comments
 (0)