Skip to content

Commit f43d3f2

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

File tree

6 files changed

+73
-5
lines changed

6 files changed

+73
-5
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

+15
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
@@ -307,6 +308,20 @@ test_lookup = do
307308
country <- lookup dept deptCountry
308309
lookup country countryCurrency
309310

311+
test_query :: Assertion
312+
test_query = do
313+
employeeCurrency 1 @?= Just 1
314+
employeeCurrency 2 @?= Nothing
315+
where
316+
employeeDept = fromList([(1,2), (3,1)])
317+
deptCountry = fromList([(1,1), (2,2)])
318+
countryCurrency = fromList([(1, 2), (2, 1)])
319+
employeeCurrency :: Int -> Maybe Int
320+
employeeCurrency name = do
321+
dept <- query name employeeDept
322+
country <- query dept deptCountry
323+
lookup country countryCurrency
324+
310325
test_findWithDefault :: Assertion
311326
test_findWithDefault = do
312327
findWithDefault 'x' 1 (fromList [(5,'a'), (3,'b')]) @?= 'x'

containers/src/Data/IntMap/Internal.hs

+18-1
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
@@ -598,7 +599,23 @@ notMember k m = not $ member k m
598599
lookup :: Key -> IntMap a -> Maybe a
599600
lookup !k = go
600601
where
601-
go (Bin p m l r) | nomatch k p m = Nothing
602+
go (Bin _p m l r)
603+
| zero k m = go l
604+
| otherwise = go r
605+
go (Tip kx x) | k == kx = Just x
606+
| otherwise = Nothing
607+
go Nil = Nothing
608+
609+
-- | /O(min(n,W))/. 'query' has identical behaviour to 'Data.IntMap.Internal.lookup', but
610+
-- will fail faster in the case that the key is not present. It is otherwise
611+
-- preferable to use `Data.IntMap.Internal.lookup'.
612+
613+
-- See Note: Local 'go' functions and capturing]
614+
query :: Key -> IntMap a -> Maybe a
615+
query !k = go
616+
where
617+
go (Bin p m l r)
618+
| nomatch k p m = Nothing
602619
| zero k m = go l
603620
| otherwise = go r
604621
go (Tip kx x) | k == kx = Just x

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)