summaryrefslogtreecommitdiff
path: root/libraries
diff options
context:
space:
mode:
authorAlexander Berntsen <alexander@plaimi.net>2014-04-18 21:41:11 +0200
committerHerbert Valerio Riedel <hvr@gnu.org>2014-04-19 11:47:52 +0200
commit44512e3c855d8fb36ab6580f4f97f842ebcf4c6c (patch)
treea88d94ae4f40afa0ab8c21b695c8239dca692de3 /libraries
parent1bf6c0e482cfe4b9dfa0b5ed18a5741ba44fc226 (diff)
downloadhaskell-44512e3c855d8fb36ab6580f4f97f842ebcf4c6c.tar.gz
Add Data.List.sortOn function (re #9004 and #2659)
`sortOn` sorts a list by comparing the results of a key function applied to each element. `sortOn f` is equivalent to `sortBy . comparing f`, but has the performance advantage of only evaluating `f` once for each element in the input list. Historical note: This was already proposed in 2008 as part of http://www.haskell.org/pipermail/libraries/2008-October/010797.html It was, however, the recent re-attempt http://www.haskell.org/pipermail/libraries/2014-April/022489.html that let `sortOn` make it into base at last. Maybe the other functions mentioned in #2659 might be worth reconsidering as well.
Diffstat (limited to 'libraries')
-rw-r--r--libraries/base/Data/List.hs14
-rw-r--r--libraries/base/changelog.md2
2 files changed, 16 insertions, 0 deletions
diff --git a/libraries/base/Data/List.hs b/libraries/base/Data/List.hs
index 09aed9d324..7f66528a44 100644
--- a/libraries/base/Data/List.hs
+++ b/libraries/base/Data/List.hs
@@ -164,6 +164,7 @@ module Data.List
-- ** Ordered lists
, sort
+ , sortOn
, insert
-- * Generalized functions
@@ -207,6 +208,8 @@ module Data.List
import Data.Maybe
import Data.Char ( isSpace )
+import Data.Ord ( comparing )
+import Data.Tuple ( fst, snd )
import GHC.Num
import GHC.Real
@@ -957,6 +960,17 @@ rqpart cmp x (y:ys) rle rgt r =
#endif /* USE_REPORT_PRELUDE */
+-- | Sort a list by comparing the results of a key function applied to each
+-- element. @sortOn f@ is equivalent to @sortBy . comparing f@, but has the
+-- performance advantage of only evaluating @f@ once for each element in the
+-- input list. This is called the decorate-sort-undecorate paradigm, or
+-- Schwartzian transform.
+--
+-- /Since: 4.7.1.0/
+sortOn :: Ord b => (a -> b) -> [a] -> [a]
+sortOn f =
+ map snd . sortBy (comparing fst) . map (\x -> let y = f x in y `seq` (y, x))
+
-- | The 'unfoldr' function is a \`dual\' to 'foldr': while 'foldr'
-- reduces a list to a summary value, 'unfoldr' builds a list from
-- a seed value. The function takes the element and returns 'Nothing'
diff --git a/libraries/base/changelog.md b/libraries/base/changelog.md
index 75e7710d55..3011fdfdc7 100644
--- a/libraries/base/changelog.md
+++ b/libraries/base/changelog.md
@@ -6,6 +6,8 @@
* Add reverse application operator `Data.Function.(&)`
+ * Add `Data.List.sortOn` sorting function
+
## 4.7.0.0 *Apr 2014*
* Bundled with GHC 7.8.1