Implement fromAscList independently
authorDavid Feuer <David.Feuer@gmail.com>
Sun, 4 Sep 2016 08:38:11 +0000 (04:38 -0400)
committerDavid Feuer <David.Feuer@gmail.com>
Mon, 5 Sep 2016 01:05:31 +0000 (21:05 -0400)
Implementing the lazy version of `fromAscList` in terms of
`fromAscListWithKey` leaks memory if there are many repeated
keys. Inlining `fromAscListWithKey` into `fromAscList` manually
should fix this. The same goes for `fromDescList`.

Data/Map/Internal.hs

index 0b8202f..8ed1d08 100644 (file)
@@ -3312,7 +3312,19 @@ foldlFB = foldlWithKey
 
 fromAscList :: Eq k => [(k,a)] -> Map k a
 fromAscList xs
-  = fromAscListWithKey (\_ x _ -> x) xs
+  = fromDistinctAscList (combineEq xs)
+  where
+  -- [combineEq f xs] combines equal elements with function [f] in an ordered list [xs]
+  combineEq xs'
+    = case xs' of
+        []     -> []
+        [x]    -> [x]
+        (x:xx) -> combineEq' x xx
+
+  combineEq' z [] = [z]
+  combineEq' z@(kz,zz) (x@(kx,xx):xs')
+    | kx==kz    = combineEq' (kx,xx) xs'
+    | otherwise = z:combineEq' x xs'
 #if __GLASGOW_HASKELL__
 {-# INLINABLE fromAscList #-}
 #endif
@@ -3326,8 +3338,19 @@ fromAscList xs
 -- > valid (fromDescList [(5,"a"), (3,"b"), (5,"b")]) == False
 
 fromDescList :: Eq k => [(k,a)] -> Map k a
-fromDescList xs
-  = fromDescListWithKey (\_ x _ -> x) xs
+fromDescList xs = fromDistinctDescList (combineEq xs)
+  where
+  -- [combineEq f xs] combines equal elements with function [f] in an ordered list [xs]
+  combineEq xs'
+    = case xs' of
+        []     -> []
+        [x]    -> [x]
+        (x:xx) -> combineEq' x xx
+
+  combineEq' z [] = [z]
+  combineEq' z@(kz,zz) (x@(kx,xx):xs')
+    | kx==kz    = combineEq' (kx,xx) xs'
+    | otherwise = z:combineEq' x xs'
 #if __GLASGOW_HASKELL__
 {-# INLINABLE fromDescList #-}
 #endif