@@ -830,6 +830,8 @@ insert k x Nil = Tip k x
830830-- > insertWith (++) 5 "xxx" (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "xxxa")]
831831-- > insertWith (++) 7 "xxx" (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "a"), (7, "xxx")]
832832-- > insertWith (++) 5 "xxx" empty == singleton 5 "xxx"
833+ --
834+ -- Also see the performance note on 'fromListWith'.
833835
834836insertWith :: (a -> a -> a ) -> Key -> a -> IntMap a -> IntMap a
835837insertWith f k x t
@@ -845,6 +847,8 @@ insertWith f k x t
845847-- > insertWithKey f 5 "xxx" (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "5:xxx|a")]
846848-- > insertWithKey f 7 "xxx" (fromList [(5,"a"), (3,"b")]) == fromList [(3, "b"), (5, "a"), (7, "xxx")]
847849-- > insertWithKey f 5 "xxx" empty == singleton 5 "xxx"
850+ --
851+ -- Also see the performance note on 'fromListWith'.
848852
849853insertWithKey :: (Key -> a -> a -> a ) -> Key -> a -> IntMap a -> IntMap a
850854insertWithKey f ! k x t@ (Bin p m l r)
@@ -870,6 +874,8 @@ insertWithKey _ k x Nil = Tip k x
870874-- > let insertLookup kx x t = insertLookupWithKey (\_ a _ -> a) kx x t
871875-- > insertLookup 5 "x" (fromList [(5,"a"), (3,"b")]) == (Just "a", fromList [(3, "b"), (5, "x")])
872876-- > insertLookup 7 "x" (fromList [(5,"a"), (3,"b")]) == (Nothing, fromList [(3, "b"), (5, "a"), (7, "x")])
877+ --
878+ -- Also see the performance note on 'fromListWith'.
873879
874880insertLookupWithKey :: (Key -> a -> a -> a ) -> Key -> a -> IntMap a -> (Maybe a , IntMap a )
875881insertLookupWithKey f ! k x t@ (Bin p m l r)
@@ -1085,6 +1091,8 @@ union m1 m2
10851091-- | \(O(n+m)\). The union with a combining function.
10861092--
10871093-- > unionWith (++) (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) == fromList [(3, "b"), (5, "aA"), (7, "C")]
1094+ --
1095+ -- Also see the performance note on 'fromListWith'.
10881096
10891097unionWith :: (a -> a -> a ) -> IntMap a -> IntMap a -> IntMap a
10901098unionWith f m1 m2
@@ -1094,6 +1102,8 @@ unionWith f m1 m2
10941102--
10951103-- > let f key left_value right_value = (show key) ++ ":" ++ left_value ++ "|" ++ right_value
10961104-- > unionWithKey f (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) == fromList [(3, "b"), (5, "5:a|A"), (7, "C")]
1105+ --
1106+ -- Also see the performance note on 'fromListWith'.
10971107
10981108unionWithKey :: (Key -> a -> a -> a ) -> IntMap a -> IntMap a -> IntMap a
10991109unionWithKey f m1 m2
@@ -2540,6 +2550,8 @@ mapKeys f = fromList . foldrWithKey (\k x xs -> (f k, x) : xs) []
25402550--
25412551-- > mapKeysWith (++) (\ _ -> 1) (fromList [(1,"b"), (2,"a"), (3,"d"), (4,"c")]) == singleton 1 "cdab"
25422552-- > mapKeysWith (++) (\ _ -> 3) (fromList [(1,"b"), (2,"a"), (3,"d"), (4,"c")]) == singleton 3 "cdab"
2553+ --
2554+ -- Also see the performance note on 'fromListWith'.
25432555
25442556mapKeysWith :: (a -> a -> a ) -> (Key -> Key ) -> IntMap a -> IntMap a
25452557mapKeysWith c f
@@ -3195,10 +3207,41 @@ fromList xs
31953207 where
31963208 ins t (k,x) = insert k x t
31973209
3198- -- | \(O(n \min(n,W))\). Create a map from a list of key\/value pairs with a combining function. See also 'fromAscListWith'.
3210+ -- | \(O(n \min(n,W))\). Build a map from a list of key\/value pairs with a combining function. See also 'fromAscListWith'.
31993211--
3200- -- > fromListWith (++) [(5,"a"), (5,"b"), (3,"b "), (3,"a"), ( 5,"c")] == fromList [(3, "ab "), (5, "cba")]
3212+ -- > fromListWith (++) [(5,"a"), (5,"b"), (3,"x "), (5,"c")] == fromList [(3, "x "), (5, "cba")]
32013213-- > fromListWith (++) [] == empty
3214+ --
3215+ -- Note the reverse ordering of @"cba"@ in the example.
3216+ --
3217+ -- The symmetric combining function @f@ is applied in a left-fold over the list, as @f new old@.
3218+ --
3219+ -- === Performance
3220+ --
3221+ -- You should ensure that the given @f@ is fast with this order of arguments.
3222+ --
3223+ -- Symmetric functions may be slow in one order, and fast in another.
3224+ -- For the common case of collecting values of matching keys in a list, as above:
3225+ --
3226+ -- The complexity of @(++) a b@ is \(O(a)\), so it is fast when given a short list as its first argument.
3227+ -- Thus:
3228+ --
3229+ -- > fromListWith (++) (replicate 1000000 (3, "x")) -- O(n), fast
3230+ -- > fromListWith (flip (++)) (replicate 1000000 (3, "x")) -- O(n²), extremely slow
3231+ --
3232+ -- because they evaluate as, respectively:
3233+ --
3234+ -- > fromList [(3, "x" ++ ("x" ++ "xxxxx..xxxxx"))] -- O(n)
3235+ -- > fromList [(3, ("xxxxx..xxxxx" ++ "x") ++ "x")] -- O(n²)
3236+ --
3237+ -- Thus, to get good performance with an operation like @(++)@ while also preserving
3238+ -- the same order as in the input list, reverse the input:
3239+ --
3240+ -- > fromListWith (++) (reverse [(5,"a"), (5,"b"), (5,"c")]) == fromList [(5, "abc")]
3241+ --
3242+ -- and it is always fast to combine singleton-list values @[v]@ with @fromListWith (++)@, as in:
3243+ --
3244+ -- > fromListWith (++) $ reverse $ map (\(k, v) -> (k, [v])) someListOfTuples
32023245
32033246fromListWith :: (a -> a -> a ) -> [(Key ,a )] -> IntMap a
32043247fromListWith f xs
@@ -3209,6 +3252,8 @@ fromListWith f xs
32093252-- > let f key new_value old_value = show key ++ ":" ++ new_value ++ "|" ++ old_value
32103253-- > fromListWithKey f [(5,"a"), (5,"b"), (3,"b"), (3,"a"), (5,"c")] == fromList [(3, "3:a|b"), (5, "5:c|5:b|a")]
32113254-- > fromListWithKey f [] == empty
3255+ --
3256+ -- Also see the performance note on 'fromListWith'.
32123257
32133258fromListWithKey :: (Key -> a -> a -> a ) -> [(Key ,a )] -> IntMap a
32143259fromListWithKey f xs
@@ -3231,6 +3276,8 @@ fromAscList = fromMonoListWithKey Nondistinct (\_ x _ -> x)
32313276-- /The precondition (input list is ascending) is not checked./
32323277--
32333278-- > fromAscListWith (++) [(3,"b"), (5,"a"), (5,"b")] == fromList [(3, "b"), (5, "ba")]
3279+ --
3280+ -- Also see the performance note on 'fromListWith'.
32343281
32353282fromAscListWith :: (a -> a -> a ) -> [(Key ,a )] -> IntMap a
32363283fromAscListWith f = fromMonoListWithKey Nondistinct (\ _ x y -> f x y)
@@ -3242,6 +3289,8 @@ fromAscListWith f = fromMonoListWithKey Nondistinct (\_ x y -> f x y)
32423289--
32433290-- > let f key new_value old_value = (show key) ++ ":" ++ new_value ++ "|" ++ old_value
32443291-- > fromAscListWithKey f [(3,"b"), (5,"a"), (5,"b")] == fromList [(3, "b"), (5, "5:b|a")]
3292+ --
3293+ -- Also see the performance note on 'fromListWith'.
32453294
32463295fromAscListWithKey :: (Key -> a -> a -> a ) -> [(Key ,a )] -> IntMap a
32473296fromAscListWithKey f = fromMonoListWithKey Nondistinct f
@@ -3263,6 +3312,8 @@ fromDistinctAscList = fromMonoListWithKey Distinct (\_ x _ -> x)
32633312-- The precise conditions under which this function works are subtle:
32643313-- For any branch mask, keys with the same prefix w.r.t. the branch
32653314-- mask must occur consecutively in the list.
3315+ --
3316+ -- Also see the performance note on 'fromListWith'.
32663317
32673318fromMonoListWithKey :: Distinct -> (Key -> a -> a -> a ) -> [(Key ,a )] -> IntMap a
32683319fromMonoListWithKey distinct f = go
0 commit comments