[commit: packages/containers] cleaned_bugfix394, master, merge-doc-target, merge-fixes-5.9, merge-restrict-fix-5.8, revert-408-bugfix_394: Add Data.Sequence.adjust' (1e227a3)
git at git.haskell.org
git at git.haskell.org
Mon Apr 17 21:43:58 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 #292 from treeowl/spitzner-nines (5cb8b26)
- 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 #294 from treeowl/sequence-adjust (ffd9be0)
- 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/1e227a342ef4125cf2c068acc2a1060a9104798c
>---------------------------------------------------------------
commit 1e227a342ef4125cf2c068acc2a1060a9104798c
Author: David Feuer <David.Feuer at gmail.com>
Date: Thu Jul 7 13:09:03 2016 -0400
Add Data.Sequence.adjust'
* Add `adjust'`, which forces the new value before installing it
in the sequence.
* Improve the documentation for `lookup`.
* Cut out some unnecessary code from `traverse`.
>---------------------------------------------------------------
1e227a342ef4125cf2c068acc2a1060a9104798c
Data/Sequence.hs | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++---
changelog.md | 2 +-
2 files changed, 62 insertions(+), 4 deletions(-)
diff --git a/Data/Sequence.hs b/Data/Sequence.hs
index e7fe97d..374e2a2 100644
--- a/Data/Sequence.hs
+++ b/Data/Sequence.hs
@@ -153,6 +153,7 @@ module Data.Sequence (
(!?), -- :: Seq a -> Int -> Maybe a
index, -- :: Seq a -> Int -> a
adjust, -- :: (a -> a) -> Int -> Seq a -> Seq a
+ adjust', -- :: (a -> a) -> Int -> Seq a -> Seq a
update, -- :: Int -> a -> Seq a -> Seq a
take, -- :: Int -> Seq a -> Seq a
drop, -- :: Int -> Seq a -> Seq a
@@ -359,6 +360,13 @@ instance MaybeForce (Node a) where
maybeRwhnf !_ = ()
{-# INLINE maybeRwhnf #-}
+-- A wrapper making mseq = seq
+newtype ForceBox a = ForceBox a
+instance MaybeForce (ForceBox a) where
+ maybeRwhnf !_ = ()
+instance Sized (ForceBox a) where
+ size _ = 1
+
-- | General-purpose finite sequences.
newtype Seq a = Seq (FingerTree (Elem a))
@@ -423,7 +431,7 @@ instance Foldable Seq where
-- `FingerTree a`, stripping off all the Elem junk, then use a weird FingerTree
-- traversing function that coerces back to Seq within the functor.
instance Traversable Seq where
- traverse f (Seq xs) = traverseFTE f (coerce xs)
+ traverse f xs = traverseFTE f (coerce xs)
traverseFTE :: Applicative f => (a -> f b) -> FingerTree a -> f (Seq b)
traverseFTE _f EmptyT = pure empty
@@ -1788,6 +1796,11 @@ scanr1 f xs = case viewr xs of
-- If the position is out of range, 'index' fails with an error.
--
-- prop> xs `index` i = toList xs !! i
+--
+-- Caution: 'index' necessarily delays retrieving the requested
+-- element until the result is forced. It can therefore lead to a space
+-- leak if the result is stored, unforced, in another structure. To retrieve
+-- an element immediately without forcing it, use 'lookup' or '(!?)'.
index :: Seq a -> Int -> a
index (Seq xs) i
-- See note on unsigned arithmetic in splitAt
@@ -1802,6 +1815,16 @@ index (Seq xs) i
-- prop> 0 <= i < length xs ==> lookup i xs == Just (toList xs !! i)
-- prop> i < 0 || i >= length xs ==> lookup i xs = Nothing
--
+-- Unlike 'index', this can be used to retrieve an element without
+-- forcing it. For example, to insert the fifth element of a sequence
+-- @xs@ into a 'Data.Map.Lazy.Map' @m@ at key @k@, you could use
+--
+-- @
+-- case lookup 5 xs of
+-- Nothing -> m
+-- Just x -> 'Data.Map.Lazy.insert' k x m
+-- @
+--
-- @since 0.5.8
lookup :: Int -> Seq a -> Maybe a
lookup i (Seq xs)
@@ -1945,14 +1968,49 @@ updateDigit v i (Four a b c d)
sab = sa + size b
sabc = sab + size c
--- | /O(log(min(i,n-i)))/. Update the element at the specified position.
--- If the position is out of range, the original sequence is returned.
+-- | /O(log(min(i,n-i)))/. Update the element at the specified position. If
+-- the position is out of range, the original sequence is returned. 'adjust'
+-- can lead to poor performance and even memory leaks, because it does not
+-- force the new value before installing it in the sequence. 'adjust'' should
+-- usually be preferred.
adjust :: (a -> a) -> Int -> Seq a -> Seq a
adjust f i (Seq xs)
-- See note on unsigned arithmetic in splitAt
| fromIntegral i < (fromIntegral (size xs) :: Word) = Seq (adjustTree (`seq` fmap f) i xs)
| otherwise = Seq xs
+-- | /O(log(min(i,n-i)))/. Update the element at the specified position.
+-- If the position is out of range, the original sequence is returned.
+-- The new value is forced before it is installed in the sequence.
+--
+-- @
+-- adjust' f i xs =
+-- case xs !? i of
+-- Nothing -> xs
+-- Just x -> let !x' = f x
+-- in update i x' xs
+-- @
+--
+-- @since 0.5.8
+adjust' :: forall a . (a -> a) -> Int -> Seq a -> Seq a
+#if __GLASGOW_HASKELL__ >= 708
+adjust' f i xs
+ -- See note on unsigned arithmetic in splitAt
+ | fromIntegral i < (fromIntegral (length xs) :: Word) =
+ coerce $ adjustTree (\ !_k (ForceBox a) -> ForceBox (f a)) i (coerce xs)
+ | otherwise = xs
+#else
+-- This is inefficient, but fixing it would take a lot of fuss and bother
+-- for little immediate gain. We can deal with that when we have another
+-- Haskell implementation to worry about.
+adjust' f i xs =
+ case xs !? i of
+ Nothing -> xs
+ Just x -> let !x' = f x
+ in update i x' xs
+#endif
+
+{-# SPECIALIZE adjustTree :: (Int -> ForceBox a -> ForceBox a) -> Int -> FingerTree (ForceBox a) -> FingerTree (ForceBox a) #-}
{-# SPECIALIZE adjustTree :: (Int -> Elem a -> Elem a) -> Int -> FingerTree (Elem a) -> FingerTree (Elem a) #-}
{-# SPECIALIZE adjustTree :: (Int -> Node a -> Node a) -> Int -> FingerTree (Node a) -> FingerTree (Node a) #-}
adjustTree :: (Sized a, MaybeForce a) => (Int -> a -> a) ->
diff --git a/changelog.md b/changelog.md
index a03b23c..fe4507a 100644
--- a/changelog.md
+++ b/changelog.md
@@ -27,7 +27,7 @@
* Add `Empty`, `:<|`, and `:|>` pattern synonyms for `Data.Sequence`.
- * Add `(!?)`, `lookup`, `chunksOf`, `cycleTaking`, `insertAt`, `deleteAt`, `intersperse`,
+ * Add `adjust'`, `(!?)`, `lookup`, `chunksOf`, `cycleTaking`, `insertAt`, `deleteAt`, `intersperse`,
`foldMapWithIndex`, and `traverseWithIndex` for `Data.Sequence`.
* Derive `Generic` and `Generic1` for `Data.Tree.Tree`, `Data.Sequence.ViewL`,
- 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 #292 from treeowl/spitzner-nines (5cb8b26)
- 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 #294 from treeowl/sequence-adjust (ffd9be0)
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the ghc-commits
mailing list