[commit: packages/containers] cleaned_bugfix394, master, merge-doc-target, merge-fixes-5.9, merge-restrict-fix-5.8, revert-408-bugfix_394: Add fromDescList and fromDistinctDescList (90b3248)
git at git.haskell.org
git at git.haskell.org
Mon Apr 17 21:44:06 UTC 2017
- Previous message: [commit: packages/containers] cleaned_bugfix394, master, merge-doc-target, merge-fixes-5.9, merge-restrict-fix-5.8, revert-408-bugfix_394: Merge pull request #295 from treeowl/map-fromDescending (a42a606)
- Next message: [commit: packages/containers] cleaned_bugfix394, master, merge-doc-target, merge-fixes-5.9, merge-restrict-fix-5.8, revert-408-bugfix_394: Merge pull request #296 from treeowl/fromDescList (1b0cd4b)
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Repository : ssh://git@git.haskell.org/containers
On branches: cleaned_bugfix394,master,merge-doc-target,merge-fixes-5.9,merge-restrict-fix-5.8,revert-408-bugfix_394
Link : http://git.haskell.org/packages/containers.git/commitdiff/90b324845fef2cd5986bdeccc819ab92a5e678b6
>---------------------------------------------------------------
commit 90b324845fef2cd5986bdeccc819ab92a5e678b6
Author: David Feuer <David.Feuer at gmail.com>
Date: Fri Jul 8 14:08:49 2016 -0400
Add fromDescList and fromDistinctDescList
The set versions are just like the map versions, pretty much.
>---------------------------------------------------------------
90b324845fef2cd5986bdeccc819ab92a5e678b6
Data/Set.hs | 2 ++
Data/Set/Base.hs | 73 +++++++++++++++++++++++++++++++++++--------------
changelog.md | 2 ++
tests/set-properties.hs | 32 ++++++++++++++++------
4 files changed, 80 insertions(+), 29 deletions(-)
diff --git a/Data/Set.hs b/Data/Set.hs
index fd8c8b9..297cee2 100644
--- a/Data/Set.hs
+++ b/Data/Set.hs
@@ -129,7 +129,9 @@ module Data.Set (
, toAscList
, toDescList
, fromAscList
+ , fromDescList
, fromDistinctAscList
+ , fromDistinctDescList
-- * Debugging
, showTree
diff --git a/Data/Set/Base.hs b/Data/Set/Base.hs
index 92bfc1d..8aabd08 100644
--- a/Data/Set/Base.hs
+++ b/Data/Set/Base.hs
@@ -181,6 +181,8 @@ module Data.Set.Base (
, toDescList
, fromAscList
, fromDistinctAscList
+ , fromDescList
+ , fromDistinctDescList
-- * Debugging
, showTree
@@ -719,7 +721,7 @@ map f = fromList . List.map f . toList
-- | /O(n)/. The
--
--- @'mapMonotonic' f s == 'map' f s@, but works only when @f@ is monotonic.
+-- @'mapMonotonic' f s == 'map' f s@, but works only when @f@ is strictly increasing.
-- /The precondition is not checked./
-- Semi-formally, we have:
--
@@ -904,24 +906,32 @@ fromList (x0 : xs0) | not_ordered x0 xs0 = fromList' (Bin 1 x0 Tip Tip) xs0
-- | /O(n)/. Build a set from an ascending list in linear time.
-- /The precondition (input list is ascending) is not checked./
fromAscList :: Eq a => [a] -> Set a
-fromAscList xs
- = fromDistinctAscList (combineEq xs)
- where
- -- [combineEq xs] combines equal elements with [const] in an ordered list [xs]
- combineEq xs'
- = case xs' of
- [] -> []
- [x] -> [x]
- (x:xx) -> combineEq' x xx
-
- combineEq' z [] = [z]
- combineEq' z (x:xs')
- | z==x = combineEq' z xs'
- | otherwise = z:combineEq' x xs'
+fromAscList xs = fromDistinctAscList (combineEq xs)
#if __GLASGOW_HASKELL__
{-# INLINABLE fromAscList #-}
#endif
+-- | /O(n)/. Build a set from a descending list in linear time.
+-- /The precondition (input list is descending) is not checked./
+fromDescList :: Eq a => [a] -> Set a
+fromDescList xs = fromDistinctDescList (combineEq xs)
+#if __GLASGOW_HASKELL__
+{-# INLINABLE fromDescList #-}
+#endif
+
+-- [combineEq xs] combines equal elements with [const] in an ordered list [xs]
+--
+-- TODO: combineEq allocates an intermediate list. It *should* be better to
+-- make fromAscListBy and fromDescListBy the fundamental operations, and to
+-- implement the rest using those.
+combineEq :: Eq a => [a] -> [a]
+combineEq [] = []
+combineEq (x : xs) = combineEq' x xs
+ where
+ combineEq' z [] = [z]
+ combineEq' z (y:ys)
+ | z == y = combineEq' z ys
+ | otherwise = z : combineEq' y ys
-- | /O(n)/. Build a set from an ascending list of distinct elements in linear time.
-- /The precondition (input list is strictly ascending) is not checked./
@@ -934,15 +944,36 @@ fromDistinctAscList (x0 : xs0) = go (1::Int) (Bin 1 x0 Tip Tip) xs0
where
go !_ t [] = t
go s l (x : xs) = case create s xs of
- (r, ys) -> go (s `shiftL` 1) (link x l r) ys
+ (r :*: ys) -> go (s `shiftL` 1) (link x l r) ys
+
+ create !_ [] = (Tip :*: [])
+ create s xs@(x : xs')
+ | s == 1 = (Bin 1 x Tip Tip :*: xs')
+ | otherwise = case create (s `shiftR` 1) xs of
+ res@(_ :*: []) -> res
+ (l :*: (y:ys)) -> case create (s `shiftR` 1) ys of
+ (r :*: zs) -> (link y l r :*: zs)
+
+-- | /O(n)/. Build a set from a descending list of distinct elements in linear time.
+-- /The precondition (input list is strictly descending) is not checked./
+
+-- For some reason, when 'singleton' is used in fromDistinctDescList or in
+-- create, it is not inlined, so we inline it manually.
+fromDistinctDescList :: [a] -> Set a
+fromDistinctDescList [] = Tip
+fromDistinctDescList (x0 : xs0) = go (1::Int) (Bin 1 x0 Tip Tip) xs0
+ where
+ go !_ t [] = t
+ go s r (x : xs) = case create s xs of
+ (l :*: ys) -> go (s `shiftL` 1) (link x l r) ys
- create !_ [] = (Tip, [])
+ create !_ [] = (Tip :*: [])
create s xs@(x : xs')
- | s == 1 = (Bin 1 x Tip Tip, xs')
+ | s == 1 = (Bin 1 x Tip Tip :*: xs')
| otherwise = case create (s `shiftR` 1) xs of
- res@(_, []) -> res
- (l, y:ys) -> case create (s `shiftR` 1) ys of
- (r, zs) -> (link y l r, zs)
+ res@(_ :*: []) -> res
+ (r :*: (y:ys)) -> case create (s `shiftR` 1) ys of
+ (l :*: zs) -> (link y l r :*: zs)
{--------------------------------------------------------------------
Eq converts the set to a list. In a lazy setting, this
diff --git a/changelog.md b/changelog.md
index 79c926b..9f3913e 100644
--- a/changelog.md
+++ b/changelog.md
@@ -28,6 +28,8 @@
* Add `fromDescList`, `fromDescListWith`, `fromDescListWithKey`,
and `fromDistinctDescList` to `Data.Map`.
+ * Add `fromDescList` and `fromDistinctDescList` to `Data.Set`.
+
* Add `Empty`, `:<|`, and `:|>` pattern synonyms for `Data.Sequence`.
* Add `adjust'`, `(!?)`, `lookup`, `chunksOf`, `cycleTaking`, `insertAt`, `deleteAt`, `intersperse`,
diff --git a/tests/set-properties.hs b/tests/set-properties.hs
index 694437c..029110d 100644
--- a/tests/set-properties.hs
+++ b/tests/set-properties.hs
@@ -42,10 +42,12 @@ main = defaultMain [ testCase "lookupLT" test_lookupLT
, testProperty "prop_IntValid" prop_IntValid
, testProperty "prop_Int" prop_Int
, testProperty "prop_Ordered" prop_Ordered
+ , testProperty "prop_DescendingOrdered" prop_DescendingOrdered
, testProperty "prop_List" prop_List
, testProperty "prop_DescList" prop_DescList
, testProperty "prop_AscDescList" prop_AscDescList
, testProperty "prop_fromList" prop_fromList
+ , testProperty "prop_fromListDesc" prop_fromListDesc
, testProperty "prop_isProperSubsetOf" prop_isProperSubsetOf
, testProperty "prop_isProperSubsetOf2" prop_isProperSubsetOf2
, testProperty "prop_isSubsetOf" prop_isSubsetOf
@@ -268,7 +270,12 @@ prop_Int xs ys = toAscList (intersection (fromList xs) (fromList ys))
prop_Ordered :: Property
prop_Ordered = forAll (choose (5,100)) $ \n ->
let xs = [0..n::Int]
- in fromAscList xs == fromList xs
+ in fromAscList xs === fromList xs
+
+prop_DescendingOrdered :: Property
+prop_DescendingOrdered = forAll (choose (5,100)) $ \n ->
+ let xs = [n,n-1..0::Int]
+ in fromDescList xs === fromList xs
prop_List :: [Int] -> Bool
prop_List xs = (sort (nub xs) == toList (fromList xs))
@@ -280,13 +287,22 @@ prop_AscDescList :: [Int] -> Bool
prop_AscDescList xs = toAscList s == reverse (toDescList s)
where s = fromList xs
-prop_fromList :: [Int] -> Bool
-prop_fromList xs
- = case fromList xs of
- t -> t == fromAscList sort_xs &&
- t == fromDistinctAscList nub_sort_xs &&
- t == List.foldr insert empty xs
- where sort_xs = sort xs
+prop_fromList :: [Int] -> Property
+prop_fromList xs =
+ t === fromAscList sort_xs .&&.
+ t === fromDistinctAscList nub_sort_xs .&&.
+ t === List.foldr insert empty xs
+ where t = fromList xs
+ sort_xs = sort xs
+ nub_sort_xs = List.map List.head $ List.group sort_xs
+
+prop_fromListDesc :: [Int] -> Property
+prop_fromListDesc xs =
+ t === fromDescList sort_xs .&&.
+ t === fromDistinctDescList nub_sort_xs .&&.
+ t === List.foldr insert empty xs
+ where t = fromList xs
+ sort_xs = reverse (sort xs)
nub_sort_xs = List.map List.head $ List.group sort_xs
{--------------------------------------------------------------------
- Previous message: [commit: packages/containers] cleaned_bugfix394, master, merge-doc-target, merge-fixes-5.9, merge-restrict-fix-5.8, revert-408-bugfix_394: Merge pull request #295 from treeowl/map-fromDescending (a42a606)
- Next message: [commit: packages/containers] cleaned_bugfix394, master, merge-doc-target, merge-fixes-5.9, merge-restrict-fix-5.8, revert-408-bugfix_394: Merge pull request #296 from treeowl/fromDescList (1b0cd4b)
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the ghc-commits
mailing list