Skip to content

Commit 2f4462f

Browse files
authored
Add Data.IntSet.alterF (#720)
* Add Data.IntSet.alterF Fixes #719. * Add Const rule and specialize for Identity * Add tests * Docs * Work around missing Show instance for Const in GHC 7.8
1 parent a6fd25a commit 2f4462f

File tree

3 files changed

+63
-1
lines changed

3 files changed

+63
-1
lines changed

containers-tests/tests/intset-properties.hs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{-# LANGUAGE CPP #-}
2+
import Control.Applicative (Const(..))
23
import Data.Bits ((.&.), popCount)
34
import Data.Word (Word)
45
import Data.IntSet
@@ -71,6 +72,8 @@ main = defaultMain [ testCase "lookupLT" test_lookupLT
7172
, testProperty "prop_partition" prop_partition
7273
, testProperty "prop_filter" prop_filter
7374
, testProperty "prop_bitcount" prop_bitcount
75+
, testProperty "prop_alterF_list" prop_alterF_list
76+
, testProperty "prop_alterF_const" prop_alterF_const
7477
]
7578

7679
----------------------------------------------------------------
@@ -425,3 +428,21 @@ prop_bitcount a w = bitcount_orig a w == bitcount_new a w
425428
where go a 0 = a
426429
go a x = go (a + 1) (x .&. (x-1))
427430
bitcount_new a x = a + popCount x
431+
432+
prop_alterF_list
433+
:: Fun Bool [Bool]
434+
-> Int
435+
-> IntSet
436+
-> Property
437+
prop_alterF_list f k s =
438+
fmap toSet (alterF (applyFun f) k s)
439+
=== Set.alterF (applyFun f) k (toSet s)
440+
441+
prop_alterF_const
442+
:: Fun Bool Bool
443+
-> Int
444+
-> IntSet
445+
-> Property
446+
prop_alterF_const f k s =
447+
getConst (alterF (Const . applyFun f) k s )
448+
=== getConst (Set.alterF (Const . applyFun f) k (toSet s))

containers/src/Data/IntSet.hs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,9 @@ module Data.IntSet (
8686
-- * Deletion
8787
, delete
8888

89+
-- * Generalized insertion/deletion
90+
, alterF
91+
8992
-- * Query
9093
, member
9194
, notMember

containers/src/Data/IntSet/Internal.hs

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ module Data.IntSet.Internal (
126126
, singleton
127127
, insert
128128
, delete
129+
, alterF
129130

130131
-- * Combine
131132
, union
@@ -188,6 +189,7 @@ module Data.IntSet.Internal (
188189
, zero
189190
) where
190191

192+
import Control.Applicative (Const(..))
191193
import Control.DeepSeq (NFData(rnf))
192194
import Data.Bits
193195
import qualified Data.List as List
@@ -222,7 +224,9 @@ import qualified GHC.Exts
222224
#endif
223225

224226
import qualified Data.Foldable as Foldable
225-
#if !MIN_VERSION_base(4,8,0)
227+
#if MIN_VERSION_base(4,8,0)
228+
import Data.Functor.Identity (Identity(..))
229+
#else
226230
import Data.Foldable (Foldable())
227231
#endif
228232

@@ -502,6 +506,40 @@ deleteBM kx bm t@(Tip kx' bm')
502506
| otherwise = t
503507
deleteBM _ _ Nil = Nil
504508

509+
-- | /O(min(n,W))/. @('alterF' f x s)@ can delete or insert @x@ in @s@ depending
510+
-- on whether it is already present in @s@.
511+
--
512+
-- In short:
513+
--
514+
-- @
515+
-- 'member' x \<$\> 'alterF' f x s = f ('member' x s)
516+
-- @
517+
--
518+
-- Note: 'alterF' is a variant of the @at@ combinator from "Control.Lens.At".
519+
alterF :: Functor f => (Bool -> f Bool) -> Key -> IntSet -> f IntSet
520+
alterF f k s = fmap choose (f member_)
521+
where
522+
member_ = member k s
523+
524+
(inserted, deleted)
525+
| member_ = (s , delete k s)
526+
| otherwise = (insert k s, s )
527+
528+
choose True = inserted
529+
choose False = deleted
530+
#ifndef __GLASGOW_HASKELL__
531+
{-# INLINE alterF #-}
532+
#else
533+
{-# INLINABLE [2] alterF #-}
534+
535+
{-# RULES
536+
"alterF/Const" forall k (f :: Bool -> Const a Bool) . alterF f k = \s -> Const . getConst . f $ member k s
537+
#-}
538+
#endif
539+
540+
#if MIN_VERSION_base(4,8,0)
541+
{-# SPECIALIZE alterF :: (Bool -> Identity Bool) -> Key -> IntSet -> Identity IntSet #-}
542+
#endif
505543

506544
{--------------------------------------------------------------------
507545
Union

0 commit comments

Comments
 (0)