diff options
author | Ryan Scott <ryan.gl.scott@gmail.com> | 2017-03-03 17:49:35 -0500 |
---|---|---|
committer | Ben Gamari <ben@smart-cactus.org> | 2017-03-04 16:04:14 -0500 |
commit | 2e43848236a4b80015d8fb09a87f6f6a746c1365 (patch) | |
tree | 71b0ba46670b0f234c311b3428b515fc417fa3a9 /libraries/base/Data/Foldable.hs | |
parent | 31b3d0c7aa35860521cfe9232270871015d693de (diff) | |
download | haskell-2e43848236a4b80015d8fb09a87f6f6a746c1365.tar.gz |
Fixes a spaceleak in `maximumBy` and `minimumBy` (#10830).
This involved changing the implementation from using
`foldr11` to using `foldl1`.
Test Plan: validate
Reviewers: austin, hvr, bgamari, dalaing, dfeuer
Reviewed By: bgamari
Subscribers: RyanGlScott, dfeuer, thomie
Differential Revision: https://phabricator.haskell.org/D3019
Diffstat (limited to 'libraries/base/Data/Foldable.hs')
-rw-r--r-- | libraries/base/Data/Foldable.hs | 30 |
1 files changed, 28 insertions, 2 deletions
diff --git a/libraries/base/Data/Foldable.hs b/libraries/base/Data/Foldable.hs index 0a8b00380d..1d9fc92ca5 100644 --- a/libraries/base/Data/Foldable.hs +++ b/libraries/base/Data/Foldable.hs @@ -551,16 +551,20 @@ all p = getAll #. foldMap (All #. p) -- | The largest element of a non-empty structure with respect to the -- given comparison function. + +-- See Note [maximumBy/minimumBy space usage] maximumBy :: Foldable t => (a -> a -> Ordering) -> t a -> a -maximumBy cmp = foldr1 max' +maximumBy cmp = foldl1 max' where max' x y = case cmp x y of GT -> x _ -> y -- | The least element of a non-empty structure with respect to the -- given comparison function. + +-- See Note [maximumBy/minimumBy space usage] minimumBy :: Foldable t => (a -> a -> Ordering) -> t a -> a -minimumBy cmp = foldr1 min' +minimumBy cmp = foldl1 min' where min' x y = case cmp x y of GT -> y _ -> x @@ -574,3 +578,25 @@ notElem x = not . elem x -- 'Nothing' if there is no such element. find :: Foldable t => (a -> Bool) -> t a -> Maybe a find p = getFirst . foldMap (\ x -> First (if p x then Just x else Nothing)) + +{- +Note [maximumBy/minimumBy space usage] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +When the type signatures of maximumBy and minimumBy were generalized to work +over any Foldable instance (instead of just lists), they were defined using +foldr1. This was problematic for space usage, as the semantics of maximumBy +and minimumBy essentially require that they examine every element of the +data structure. Using foldr1 to examine every element results in space usage +proportional to the size of the data structure. For the common case of lists, +this could be particularly bad (see Trac #10830). + +For the common case of lists, switching the implementations of maximumBy and +minimumBy to foldl1 solves the issue, as GHC's strictness analysis can then +make these functions only use O(1) stack space. It is perhaps not the optimal +way to fix this problem, as there are other conceivable data structures +(besides lists) which might benefit from specialized implementations for +maximumBy and minimumBy (see +https://ghc.haskell.org/trac/ghc/ticket/10830#comment:26 for a further +discussion). But using foldl1 is at least always better than using foldr1, so +GHC has chosen to adopt that approach for now. +-} |