data-ordlist 0.4.4 → 0.4.5
raw patch · 3 files changed
+154/−60 lines, 3 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Data.List.Ordered: foldt :: (a -> a -> a) -> a -> [a] -> a
+ Data.List.Ordered: foldt' :: (a -> a -> a) -> a -> [a] -> a
+ Data.List.Ordered: minus' :: Ord a => [a] -> [a] -> [a]
+ Data.List.Ordered: minusBy' :: (a -> a -> Ordering) -> [a] -> [a] -> [a]
Files
- CHANGES +28/−5
- Data/List/Ordered.hs +124/−53
- data-ordlist.cabal +2/−2
CHANGES view
@@ -1,15 +1,33 @@+Version 0.4.5: (2012-03-12)++ * New function, `minus'`++ * Exported `foldt` and `foldt'`++ * Documentation improvements++ * Reverted the implementation of `mergeAll` and `unionAll` to version+ 0.4.2 because the simplified implementation would force the head of+ the inner list appearing at the next highest power of 2 well before+ it was necessary to do so.+ Version 0.4.4: (2010-12-24) * Simplified the implementation of `mergeAll` and `unionAll` based on comments from Will Ness. + <http://www.haskell.org/pipermail/haskell-cafe/2010-December/087587.html>+ Version 0.4.3: (2010-03-02) * Improved the implementation of `nubSort`, mirroring the improvements made- to `Data.List.sort` currently in GHC HEAD. Instead of initially breaking- the input list into singletons before the merge process, the improved- version breaks the input list into monotonic runs.+ to `Data.List.sort` in GHC-6.13.20091224 and first released in GHC-7.0.1.+ Thanks to Gwern Branwen for calling the change to my attention. Instead+ of initially breaking the input list into singletons before the merge+ process, the improved version breaks the input list into monotonic runs. + <http://www.haskell.org/pipermail/libraries/2010-March/013066.html>+ * Minor formatting improvements in the Haddock documentation. Version 0.4.2: (2010-02-18)@@ -18,15 +36,20 @@ of lists. Thanks to Omar Antolín Camarena for reporting the bug and Heinrich Apfelmus for some useful comments. + <http://www.haskell.org/pipermail/haskell-cafe/2010-February/073403.html>+ <http://www.haskell.org/pipermail/haskell-cafe/2010-February/073437.html>+ * Added regression test to test suite. Version 0.4.1: (2010-02-17) * Simplified the implementation of `mergeAll` and `unionAll` thanks to some pointers by Heinrich Apfelmus. This introduced an infinite- non-productive loop into `unionAll`, which was later fixed without+ non-productive loop into `unionAll`, which was fixed in 0.4.2 without giving up the simplifications. + <http://www.haskell.org/pipermail/haskell-cafe/2010-February/073356.html>+ * Minor documentation fixes Version 0.4: (2010-02-15)@@ -57,7 +80,7 @@ mailing list on 2007 Jul 22. It also appears as "BayerPrimes.hs" inside of Melissa O'Neill's "haskell-primes.zip": - <http://www.mail-archive.com/haskell-cafe@haskell.org/msg27612.html>+ <http://www.haskell.org/pipermail/haskell-cafe/2007-July/029391.html> <http://www.cs.hmc.edu/~oneill/code/haskell-primes.zip> Version 0.2: (2010-02-07)
Data/List/Ordered.hs view
@@ -1,23 +1,35 @@ ----------------------------------------------------------------------------- -- | -- Module : Data.List.Ordered--- Copyright : (c) 2009-2010 Leon P Smith+-- Copyright : (c) 2009-2011 Leon P Smith -- License : BSD3 -- -- Maintainer : leon@melding-monads.com -- Stability : experimental -- Portability : portable ----- This module implements bag and set operations on ordered lists.--- Except for variations of the 'sort' and 'isSorted' functions,--- every function assumes that any list arguments are sorted lists.--- Assuming this precondition is met, every resulting list is also+-- This module implements bag and set operations on ordered lists. For the+-- purposes of this module, a \"bag\" (or \"multiset\") is a non-decreasing+-- list, whereas a \"set\" is a strictly ascending list. Bags are sorted+-- lists that may contain duplicates, whereas sets are sorted lists that+-- do not contain duplicates.+--+-- Except for the 'nub', 'sort', 'nubSort', and 'isSorted' families of+-- functions, every function assumes that any list arguments are sorted+-- lists. Assuming this precondition is met, every resulting list is also -- sorted. ----- Note that these functions handle multisets, and are left-biased.--- Thus, even assuming the arguments are sorted, 'isect' does not always--- return the same results as Data.List.intersection, due to multiplicity.+-- Because 'isect' handles multisets correctly, it does not return results+-- comparable to @Data.List.'Data.List.intersect'@ on them. Thus @isect@+-- is more than just a more efficient @intersect@ on ordered lists. Similar+-- statements apply to other associations between functions this module and+-- functions in @Data.List@, such as 'union' and @Data.List.'union'@. --+-- All functions in this module are left biased. Elements that appear in+-- earlier arguments have priority over equal elements that appear in later+-- arguments, and elements that appear earlier in a single list have+-- priority over equal elements that appear later in that list.+-- ----------------------------------------------------------------------------- module Data.List.Ordered@@ -35,10 +47,11 @@ , isect, isectBy , union, unionBy , minus, minusBy+ , minus', minusBy' , xunion, xunionBy , merge, mergeBy- , mergeAll , mergeAllBy- , unionAll , unionAllBy+ , mergeAll, mergeAllBy+ , unionAll, unionAllBy -- * Lists to Ordered Lists , nub, nubBy@@ -47,11 +60,15 @@ , nubSort, nubSortBy , nubSortOn, nubSortOn' + -- * Miscellaneous folds+ , foldt, foldt'+ ) where -import Data.List(sort,sortBy)+import Data.List(sort,sortBy,intersect) --- | The 'isSorted' predicate returns 'True' if the elements of a list occur in non-descending order, equivalent to @'isSortedBy' ('<=')@.+-- | The 'isSorted' predicate returns 'True' if the elements of a list occur+-- in non-descending order, equivalent to @'isSortedBy' ('<=')@. isSorted :: Ord a => [a] -> Bool isSorted = isSortedBy (<=) @@ -242,6 +259,29 @@ EQ -> loop xs ys GT -> loop (x:xs) ys +-- | The 'minus'' function computes the difference of two ordered lists.+-- The result consists of elements from the first list that do not appear+-- in the second list. If the first input is a set, then the output is+-- a set.+--+-- > minus' [ 1,2, 3,4 ] [ 3,4, 5,6 ] == [ 1,2 ]+-- > minus' [ 1, 2,2,2 ] [ 1,1,1, 2,2 ] == []+-- > minus' [ 1,1, 2,2 ] [ 2 ] == [ 1,1 ]+minus' :: Ord a => [a] -> [a] -> [a]+minus' = minusBy' compare++-- | The 'minusBy'' function is the non-overloaded version of 'minus''.+minusBy' :: (a -> a -> Ordering) -> [a] -> [a] -> [a]+minusBy' cmp = loop+ where+ loop [] _ys = []+ loop xs [] = xs+ loop (x:xs) (y:ys)+ = case cmp x y of+ LT -> x : loop xs (y:ys)+ EQ -> loop xs (y:ys)+ GT -> loop (x:xs) ys+ -- | The 'xunion' function computes the exclusive union of two ordered lists. -- An element occurs in the output as many times as the absolute difference -- between the number of occurrences in the inputs. If both inputs@@ -266,7 +306,8 @@ -- | The 'merge' function combines all elements of two ordered lists. -- An element occurs in the output as many times as the sum of the--- occurrences in the lists.+-- occurrences in both lists. The output is a set if and only if+-- the inputs are disjoint sets. -- -- > merge [ 1,2, 3,4 ] [ 3,4, 5,6 ] == [ 1,2, 3,3,4,4, 5,6 ] -- > merge [ 1, 2,2,2 ] [ 1,1,1, 2,2 ] == [ 1,1,1,1, 2,2,2,2,2 ]@@ -310,7 +351,7 @@ sort = sortBy compare sortBy :: (a -> a -> Ordering) -> [a] -> [a]-sortBy cmp = foldTree (mergeBy cmp) [] . map (\x -> [x])+sortBy cmp = foldt (mergeBy cmp) [] . map (\x -> [x]) -} -- | The 'sortOn' function provides the decorate-sort-undecorate idiom,@@ -327,14 +368,17 @@ sortOn' f = sortBy (\x y -> compare (f x) (f y)) -- | The 'nubSort' function is equivalent to @'nub' '.' 'sort'@, except--- somewhat more efficient as duplicates are removed as it sorts. It is--- essentially Data.List.sort, with 'merge' replaced by 'union'.+-- that duplicates are removed as it sorts. It is essentially the same+-- implementation as @Data.List.sort@, with 'merge' replaced by 'union'.+-- Thus the performance of 'nubSort' should better than or nearly equal+-- to 'sort' alone. It is faster than @'nub' '.' 'sort'@ when the+-- input contains significant quantities of duplicated elements. nubSort :: Ord a => [a] -> [a] nubSort = nubSortBy compare -- | The 'nubSortBy' function is the non-overloaded version of 'nubSort'. nubSortBy :: (a -> a -> Ordering) -> [a] -> [a]-nubSortBy cmp = foldTree' (unionBy cmp) [] . runs+nubSortBy cmp = foldt' (unionBy cmp) [] . runs where -- 'runs' partitions the input into sublists that are monotonic, -- contiguous, and non-overlapping. Descending runs are reversed@@ -366,7 +410,7 @@ nubSortOn :: Ord b => (a -> b) -> [a] -> [a] nubSortOn f = map snd . nubSortOn' fst . map (\x -> (f x, x)) --- | This variant of 'nubSortOn' recomputes the sorting key for each comparison.+-- | This variant of 'nubSortOn' recomputes the sorting key for each comparison nubSortOn' :: Ord b => (a -> b) -> [a] -> [a] nubSortOn' f = nubSortBy (\x y -> compare (f x) (f y)) @@ -377,7 +421,6 @@ -- > nub [1,1,1,2,2] == [1,2] -- > nub [2,0,1,3,3] == [2,3] -- > nub = nubBy (<)- nub :: Ord a => [a] -> [a] nub = nubBy (<) @@ -398,13 +441,12 @@ | p x y = y : loop y ys | otherwise = loop x ys --- | The function @'foldTree'' plus zero@ computes the sum of a list--- using a balanced tree of operations. 'foldTree'' necessarily diverges--- on infinite lists, hence it is a stricter variant of 'foldTree'.--- 'foldTree'' is used in the implementation of 'sort' and 'nubSort'.--foldTree' :: (a -> a -> a) -> a -> [a] -> a-foldTree' plus zero xs+-- | The function @'foldt'' plus zero@ computes the sum of a list+-- using a balanced tree of operations. 'foldt'' necessarily diverges+-- on infinite lists, hence it is a stricter variant of 'foldt'.+-- 'foldt'' is used in the implementation of 'sort' and 'nubSort'.+foldt' :: (a -> a -> a) -> a -> [a] -> a+foldt' plus zero xs = case xs of [] -> zero (_:_) -> loop xs@@ -415,14 +457,13 @@ pairs (x:y:zs) = plus x y : pairs zs pairs zs = zs --- | The function @'foldTree' plus zero@ computes the sum of a list using+-- | The function @'foldt' plus zero@ computes the sum of a list using -- a sequence of balanced trees of operations. Given an appropriate @plus@ -- operator, this function can be productive on an infinite list, hence it--- is lazier than 'foldTree''. 'foldTree' is used in the implementation of+-- is lazier than 'foldt''. 'foldt' is used in the implementation of -- 'mergeAll' and 'unionAll'.--foldTree :: (a -> a -> a) -> a -> [a] -> a-foldTree plus zero xs+foldt :: (a -> a -> a) -> a -> [a] -> a+foldt plus zero xs = case xs of [] -> zero (_:_) -> loop xs@@ -433,6 +474,15 @@ pairs (x:y:zs) = plus x y : pairs zs pairs zs = zs +-- helper functions used in 'mergeAll' and 'unionAll'++data People a = VIP a (People a) | Crowd [a]++serve (VIP x xs) = x:serve xs+serve (Crowd xs) = xs++vips xss = [ VIP x (Crowd xs) | (x:xs) <- xss ]+ -- | The 'mergeAll' function merges a (potentially) infinite number of -- ordered lists, under the assumption that the heads of the inner lists -- are sorted. An element is duplicated in the result as many times as@@ -440,22 +490,28 @@ -- -- The 'mergeAll' function is closely related to @'foldr' 'merge' []@. -- The former does not assume that the outer list is finite, whereas--- the latter makes no assumption about the heads of the inner lists.+-- the latter does not assume that the heads of the inner lists are sorted. -- When both sets of assumptions are met, these two functions are -- equivalent. -- -- This implementation of 'mergeAll' uses a tree of comparisons, and is -- based on input from Dave Bayer, Heinrich Apfelmus, Omar Antolin Camarena,--- and Will Ness.+-- and Will Ness. See @CHANGES@ for details. mergeAll :: Ord a => [[a]] -> [a] mergeAll = mergeAllBy compare --- | The 'mergeAllBy' function is the non-overloaded variant of the 'mergeAll' function.+-- | The 'mergeAllBy' function is the non-overloaded variant of the 'mergeAll'+-- function. mergeAllBy :: (a -> a -> Ordering) -> [[a]] -> [a]-mergeAllBy cmp = foldTree merge' []+mergeAllBy cmp = serve . foldt merge' (Crowd []) . vips where- merge' [] ys = ys- merge' (x:xs) ys = x : mergeBy cmp xs ys+ merge' (VIP x xs) ys = VIP x (merge' xs ys)+ merge' (Crowd []) ys = ys+ merge' (Crowd xs) (Crowd ys) = Crowd (mergeBy cmp xs ys)+ merge' xs@(Crowd (x:xt)) ys@(VIP y yt)+ = case cmp x y of+ GT -> VIP y (merge' xs yt)+ _ -> VIP x (merge' (Crowd xt) ys) -- | The 'unionAll' computes the union of a (potentially) infinite number -- of lists, under the assumption that the heads of the inner lists@@ -463,27 +519,42 @@ -- the maximum number of occurrences in any single list. Thus, the result -- is a set if and only if every inner list is a set. ----- Analogous to 'mergeAll', 'unionAll' is closely related to--- @'foldr' 'union' []@; The outer does not assume that the outer list--- is finite, whereas the right fold does not assume anything about the--- heads of the inner lists. When both sets of assumptions are met, the--- functions are equivalent.+-- The 'unionAll' function is closely related to @'foldr' 'union' []@.+-- The former does not assume that the outer list is finite, whereas+-- the latter does not assume that the heads of the inner lists are sorted.+-- When both sets of assumptions are met, these two functions are+-- equivalent. ----- This implementation is also based on implicit heaps, providing--- a tree of comparisons.+-- Note that there is no simple way to express 'unionAll' in terms of+-- 'mergeAll' or vice versa on arbitrary valid inputs. They are related+-- via 'nub' however, as @'nub' . 'mergeAll' == 'unionAll' . 'map' 'nub'@.+-- If every list is a set, then @map nub == id@, and in this special case+-- (and only in this special case) does @nub . mergeAll == unionAll@.+--+-- This implementation of 'unionAll' uses a tree of comparisons, and is+-- based on input from Dave Bayer, Heinrich Apfelmus, Omar Antolin Camarena,+-- and Will Ness. See @CHANGES@ for details. unionAll :: Ord a => [[a]] -> [a] unionAll = unionAllBy compare --- | The 'unionAllBy' function is the non-overloaded variant of the 'unionAll' function.+-- | The 'unionAllBy' function is the non-overloaded variant of the 'unionAll'+-- function. unionAllBy :: (a -> a -> Ordering) -> [[a]] -> [a]-unionAllBy cmp = foldTree union' []+unionAllBy cmp = serve . foldt union' (Crowd []) . vips where msg = "Data.List.Ordered.unionAllBy: the heads of the lists are not sorted" - union' [] ys = ys- union' (x:xs) ys = x : case ys of- [] -> xs- (y:yt) -> case cmp x y of- LT -> unionBy cmp xs ys- EQ -> unionBy cmp xs yt- GT -> error msg+ union' (VIP x xs) ys+ = VIP x $ case ys of+ Crowd _ -> union' xs ys+ VIP y yt -> case cmp x y of+ LT -> union' xs ys+ EQ -> union' xs yt+ GT -> error msg+ union' (Crowd []) ys = ys+ union' (Crowd xs) (Crowd ys) = Crowd (unionBy cmp xs ys)+ union' xs@(Crowd (x:xt)) ys@(VIP y yt)+ = case cmp x y of+ LT -> VIP x (union' (Crowd xt) ys)+ EQ -> VIP x (union' (Crowd xt) yt)+ GT -> VIP y (union' xs yt)
data-ordlist.cabal view
@@ -1,5 +1,5 @@ Name: data-ordlist-Version: 0.4.4+Version: 0.4.5 Description: This module provides set and multiset operations on ordered lists. License: BSD3@@ -22,4 +22,4 @@ source-repository this type: darcs location: http://patch-tag.com/r/lpsmith/data-ordlist/pullrepo- tag: 0.4.4+ tag: 0.4.5