monoids 0.1.32 → 0.1.33
raw patch · 16 files changed
+1440/−121 lines, 16 files
Files
- Data/Monoid/Applicative.hs +2/−0
- Data/Monoid/Lexical/SourcePosition.hs +6/−6
- Data/Monoid/Monad.hs +2/−0
- Data/Ring/Algebra.hs +4/−3
- Data/Ring/Boolean.hs +1/−0
- Data/Ring/FromNum.hs +1/−0
- Data/Ring/ModularArithmetic.hs +1/−0
- Data/Ring/Module/AutomaticDifferentiation.hs +8/−7
- Data/Ring/Semi/BitSet.hs +118/−81
- Data/Ring/Semi/Kleene.hs +10/−0
- Data/Ring/Semi/Natural.hs +1/−0
- Data/Ring/Semi/Near.hs +22/−23
- Data/Ring/Semi/Ord.hs +2/−0
- Data/Ring/Semi/Tropical.hs +1/−0
- Data/Set/Unboxed.hs +1258/−0
- monoids.cabal +3/−1
Data/Monoid/Applicative.hs view
@@ -73,6 +73,8 @@ instance Alternative f => Reducer (f a) (Alt f a) where unit = Alt +instance (Alternative f, Monoid a) => Ringoid (Alt f a)+ instance (Alternative f, Monoid a) => RightSemiNearRing (Alt f a) -- | if @m@ is a 'Module' over @r@ and @f@ is a 'Applicative' then @f `App` m@ is a 'Module' over @r@ as well
Data/Monoid/Lexical/SourcePosition.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, OverloadedStrings #-}+{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, OverloadedStrings, BangPatterns #-} ----------------------------------------------------------------------------- -- |@@ -44,15 +44,15 @@ -- | A 'Monoid' of partial information about locations in a source file. -- This is polymorphic in the kind of information you want to maintain about each source file. data SourcePosition file - = Pos file {-# UNPACK #-} !SourceLine !SourceColumn -- ^ An absolute position in a file is known, or an overriding #line directive has been seen- | Lines {-# UNPACK #-} !SourceLine !SourceColumn -- ^ We've seen some carriage returns.- | Columns {-# UNPACK #-} !SourceColumn -- ^ We've only seen part of a line.- | Tab {-# UNPACK #-} !SourceColumn !SourceColumn -- ^ We have an unhandled tab to deal with.+ = Pos file {-# UNPACK #-} !SourceLine {-# UNPACK #-} !SourceColumn -- ^ An absolute position in a file is known, or an overriding #line directive has been seen+ | Lines {-# UNPACK #-} !SourceLine {-# UNPACK #-} !SourceColumn -- ^ We've seen some carriage returns.+ | Columns {-# UNPACK #-} !SourceColumn -- ^ We've only seen part of a line.+ | Tab {-# UNPACK #-} !SourceColumn {-# UNPACK #-} !SourceColumn -- ^ We have an unhandled tab to deal with. deriving (Read,Show,Eq) -- | Compute the location of the next standard 8-column aligned tab nextTab :: Int -> Int-nextTab x = x + (8 - (x-1) `mod` 8)+nextTab !x = x + (8 - (x-1) `mod` 8) instance Functor SourcePosition where fmap g (Pos f l c) = Pos (g f) l c
Data/Monoid/Monad.hs view
@@ -83,6 +83,8 @@ instance MonadPlus m => Reducer (m a) (MonadSum m a) where unit = MonadSum +instance (MonadPlus m, Monoid a) => Ringoid (MonadSum m a)+ instance (MonadPlus m, Monoid a) => RightSemiNearRing (MonadSum m a) -- | if @m@ is a 'Module' over @r@ and @f@ is a 'Monad' then @f `Mon` m@ is a 'Module' as well
Data/Ring/Algebra.hs view
@@ -1,13 +1,14 @@ {-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, FlexibleContexts #-} module Data.Ring.Algebra ( module Data.Ring.Module- , Algebra+ , RAlgebra ) where import Data.Ring.Module --- | +-- | Algebra over a (near) (semi) ring.+-- -- @r *. (x * y) = (r *. x) * y = x * (r *. y)@ -- -- @(x * y) .* r = y * (x .* r) = (y .* r) * x@-class (r `Module` m, Multiplicative m) => Algebra r m +class (r `Module` m, Multiplicative m) => RAlgebra r m
Data/Ring/Boolean.hs view
@@ -37,6 +37,7 @@ one = BoolRing True BoolRing a `times` BoolRing b = BoolRing (a && b) +instance Ringoid BoolRing instance LeftSemiNearRing BoolRing instance RightSemiNearRing BoolRing instance SemiRing BoolRing
Data/Ring/FromNum.hs view
@@ -38,6 +38,7 @@ times = (*) -- you can assume these, but you're probably lying to yourself+instance Num a => Ringoid (FromNum a) instance Num a => LeftSemiNearRing (FromNum a) instance Num a => RightSemiNearRing (FromNum a) instance Num a => SemiRing (FromNum a)
Data/Ring/ModularArithmetic.hs view
@@ -65,6 +65,7 @@ minus = (-) gsubtract = subtract +instance (Modular s a, Integral a) => Ringoid (a `Mod` s) instance (Modular s a, Integral a) => LeftSemiNearRing (a `Mod` s) instance (Modular s a, Integral a) => RightSemiNearRing (a `Mod` s) instance (Modular s a, Integral a) => SemiRing (a `Mod` s)
Data/Ring/Module/AutomaticDifferentiation.hs view
@@ -26,10 +26,10 @@ data D s r m = D r m deriving (Show,Read) -lift :: Monoid m => r -> D s r m+lift :: (r `Module` m) => r -> D s r m lift x = D x zero -infinitesimal :: (Monoid r, Multiplicative m) => D s r m+infinitesimal :: (r `Module` m, Ringoid m) => D s r m infinitesimal = D zero one instance Eq r => Eq (D s r m) where@@ -38,7 +38,7 @@ instance Ord r => Ord (D s r m) where D x _ `compare` D y _ = compare x y -instance (Monoid r, Monoid m) => Monoid (D s r m) where+instance (r `Module` m) => Monoid (D s r m) where mempty = D mempty mempty D x m `mappend` D y n = D (x `mappend` y) (m `mappend` n) @@ -64,12 +64,13 @@ recip (D x x') = D (recip x) (-x'/x/x) fromRational x = D (fromRational x) 0 +instance (Ringoid r, r `Module` m) => Ringoid (D s r m) instance (LeftSemiNearRing r, Module r m) => LeftSemiNearRing (D s r m) instance (RightSemiNearRing r, Module r m) => RightSemiNearRing (D s r m)-instance (SemiRing r, Module r m) => SemiRing (D s r m)-instance (Ring r, Module r m, Group m) => Ring (D s r m)+instance (SemiRing r, r `Module` m) => SemiRing (D s r m)+instance (Ring r, r `Module` m, Group m) => Ring (D s r m) -instance (c `Reducer` r, c `Reducer` m) => Reducer c (D s r m) where+instance (r `Module` m, c `Reducer` r, c `Reducer` m) => Reducer c (D s r m) where unit c = D (unit c) (unit c) c `cons` D x m = D (c `cons` x) (c `cons` m) D x m `snoc` c = D (x `snoc` c) (m `snoc` c)@@ -81,6 +82,6 @@ instance (CoArbitrary r, CoArbitrary m) => CoArbitrary (D s r m) where coarbitrary (D r m) = coarbitrary r >< coarbitrary m -d :: (Monoid r, Multiplicative m) => (forall s. D s r m -> D s r m) -> (r,m)+d :: (r `Module` m, Ringoid m) => (forall s. D s r m -> D s r m) -> (r,m) d f = (y,y') where D y y' = f infinitesimal
Data/Ring/Semi/BitSet.hs view
@@ -14,6 +14,7 @@ -- can return negative values, support efficient intersection and union -- and allow complementing of the set with respect to the bounds of the -- enumeration+-- ------------------------------------------------------------------------------- module Data.Ring.Semi.BitSet@@ -41,9 +42,10 @@ , toInteger ) where -import Prelude hiding ( null, exponent, toInteger )+import Prelude hiding ( null, exponent, toInteger, foldl, foldr, foldl1, foldr1 ) import Data.Bits hiding ( complement ) import qualified Data.Bits as Bits+import Data.Foldable hiding ( toList ) import Data.Data import Data.Ring.Semi.Natural import Data.Ring.Semi@@ -53,60 +55,71 @@ import Text.Read import Text.Show +-- | Set operations optimized for tightly grouped sets or nearly universal sets with a close by group of elements missing.+-- Stores itself like an arbitrary precision floating point number, tracking the least valued member of the set and an+-- Integer comprised of the members. data BitSet a = BS { _countAtLeast :: {-# UNPACK #-} !Int -- ^ A conservative upper bound on the element count. -- If negative, we are complemented with respect to the universe , _countAtMost :: {-# UNPACK #-} !Int -- ^ A conservative lower bound on the element count. -- If negative, we are complemented with respect to the universe- , _count :: Int -- ^ Lazy element count used when the above two disagree. O(1) environment size+ , _count :: Int -- ^ Lazy element count used when the above two disagree. O(1) environment size , exponent :: {-# UNPACK #-} !Int -- ^ Low water mark. index of the least element potentially in the set. , _hwm :: {-# UNPACK #-} !Int -- ^ High water mark. index of the greatest element potentially in the set. , mantissa :: {-# UNPACK #-} !Integer -- ^ the set of bits starting from the exponent. -- if negative, then we are complmenented with respect to universe- , _universe :: (Int,Int) -- ^ invariant: whenever mantissa < 0 => universe = (fromEnum minBound,fromEnum maxBound)- } deriving (Data, Typeable)+ , _universe :: (Int,Int) -- ^ invariant: whenever mantissa < 0, universe = (fromEnum minBound,fromEnum maxBound)+ , _fromEnum :: Int -> a -- ^ self-contained extraction behavior, enables Foldable+ } deriving (Typeable) +-- | omit reflection to preserve abstraction+instance (Enum a, Data a) => Data (BitSet a) where+ gfoldl f z im = z fromList `f` toList im+ toConstr _ = error "toConstr"+ gunfold _ _ = error "gunfold"+ dataTypeOf _ = mkNorepType "Data.Ring.Semi.BitSet.BitSet"+ dataCast1 f = gcast1 f + -- | Internal smart constructor. Forces count whenever it is pigeonholed.-bs :: Int -> Int -> Int -> Int -> Int -> Integer -> (Int,Int) -> BitSet a-bs !a !b c !l !h !m u | a == b = BS a a a l h m u- | otherwise = BS a b c l h m u+bs :: Enum a => Int -> Int -> Int -> Int -> Int -> Integer -> (Int,Int) -> BitSet a+bs !a !b c !l !h !m u | a == b = BS a a a l h m u toEnum+ | otherwise = BS a b c l h m u toEnum {-# INLINE bs #-} --- | /O(d)/ where /d/ is absolute deviation in fromEnum over the set-toList :: Enum a => BitSet a -> [a]-toList (BS _ _ _ l h m u) - | m < 0 = map toEnum [ul..max (pred l) ul] ++ toList' l (map toEnum [min (succ h) uh..uh])+-- | /O(d)/ where /d/ is absolute deviation in the output of fromEnum over the set+toList :: BitSet a -> [a]+toList (BS _ _ _ l h m u f) + | m < 0 = map f [ul..max (pred l) ul] ++ toList' l (map f [min (succ h) uh..uh]) | otherwise = toList' 0 [] where ~(ul,uh) = u- toList' :: Enum a => Int -> [a] -> [a]- toList' !n t | n > h = t- | testBit m (n - l) = toEnum n : toList' (n+1) t- | otherwise = toList' (n+1) t+ toList' !n t + | n > h = t+ | testBit m (n - l) = f n : toList' (n+1) t+ | otherwise = toList' (n+1) t {-# INLINE toList #-} -- | /O(1)/ The empty set. Permits /O(1)/ null and size.-empty :: BitSet a-empty = BS 0 0 0 0 0 0 undefined+empty :: Enum a => BitSet a+empty = BS 0 0 0 0 0 0 undefined toEnum {-# INLINE empty #-} -- | /O(1)/ Construct a @BitSet@ with a single element. Permits /O(1)/ null and size singleton :: Enum a => a -> BitSet a -singleton x = BS 1 1 1 e e 1 undefined where e = fromEnum x+singleton x = BS 1 1 1 e e 1 undefined toEnum where e = fromEnum x {-# INLINE singleton #-} --- | /O(1|d)/ Is the 'BitSet' empty? May be faster than checking if @'size' == 0@ after union.--- Operations that require a recount are noted.+-- | /O(1)/ amortized cost. Is the 'BitSet' empty? May be faster than checking if @'size' == 0@. null :: BitSet a -> Bool-null (BS a b c _ _ _ _) +null (BS a b c _ _ _ _ _) | a > 0 = False | b == 0 = True | otherwise = c == 0 {-# INLINE null #-} --- | /O(1|d)/ The number of elements in the bit set.+-- | /O(1)/ amortized cost. The number of elements in the bit set. size :: BitSet a -> Int-size (BS a b c _ _ m (ul,uh)) +size (BS a b c _ _ m (ul,uh) _) | a == b, m >= 0 = a | a == b = uh - ul - a | m >= 0 = c@@ -120,18 +133,18 @@ -- | /O(d)/ Complements a 'BitSet' with respect to the bounds of @a@. Preserves order of 'null' and 'size' complement :: (Enum a, Bounded a) => BitSet a -> BitSet a -complement r@(BS a b c l h m _) = BS (Bits.complement b) (Bits.complement a) (Bits.complement c) l h (Bits.complement m) u where+complement r@(BS a b c l h m _ f) = BS (Bits.complement b) (Bits.complement a) (Bits.complement c) l h (Bits.complement m) u f where u = (fromEnum (minBound `asArgTypeOf` r), fromEnum (maxBound `asArgTypeOf` r)) {-# INLINE complement #-} -- | /O(d)/ unsafe internal method: complement a set that has already been complemented at least once. recomplement :: BitSet a -> BitSet a -recomplement (BS a b c l h m u) = BS (Bits.complement b) (Bits.complement a) (Bits.complement c) l h (Bits.complement m) u+recomplement (BS a b c l h m u f) = BS (Bits.complement b) (Bits.complement a) (Bits.complement c) l h (Bits.complement m) u f {-# INLINE recomplement #-} -- | /O(d)/ unsafe internal method: complement a set that has already been complemented at least once. pseudoComplement :: BitSet a -> (Int,Int) -> BitSet a -pseudoComplement (BS a b c l h m _) u = BS (Bits.complement b) (Bits.complement a) (Bits.complement c) l h (Bits.complement m) u+pseudoComplement (BS a b c l h m _ f) u = BS (Bits.complement b) (Bits.complement a) (Bits.complement c) l h (Bits.complement m) u f {-# INLINE pseudoComplement #-} -- | /O(d * n)/ Make a 'BitSet' from a list of items.@@ -146,21 +159,23 @@ where l = fromEnum c fromDistinctAscList' :: Enum a => [a] -> Int -> Int -> Integer -> BitSet a- fromDistinctAscList' [] !n !h !m = BS n n n l h m undefined- fromDistinctAscList' (c':cs') !n _ !m = fromDistinctAscList' cs' (n+1) h' (setBit m (h' - l))- where- h' = fromEnum c'+ fromDistinctAscList' [] !n !h !m = BS n n n l h m undefined toEnum+ fromDistinctAscList' (c':cs') !n _ !m = + let h' = fromEnum c' in + fromDistinctAscList' cs' (n+1) h' (setBit m (h' - l)) {-# INLINE fromDistinctAscList #-} -- | /O(d)/ Insert a single element of type @a@ into the 'BitSet'. Preserves order of 'null' and 'size' insert :: Enum a => a -> BitSet a -> BitSet a-insert x r@(BS a b c l h m u) +insert x r@(BS a b c l h m u _) | m < 0, e < l = r | m < 0, e > h = r- | e < l = bs (a+1) (b+1) (c+1) e h (shiftL m (l - e) .|. 1) u- | e > h = bs (a+1) (b+1) (c+1) l p (setBit m p) u- | testBit m p = r - | otherwise = bs (a+1) (b+1) (c+1) l h (setBit m p) u+ | b == 0 = singleton x+ | a == -1 = r+ | e < l = bs (a+1) (b+1) (c+1) e h (shiftL m (l - e) .|. 1) u+ | e > h = bs (a+1) (b+1) (c+1) l p (setBit m p) u+ | testBit m p = r + | otherwise = bs (a+1) (b+1) (c+1) l h (setBit m p) u where e = fromEnum x p = e - l @@ -168,13 +183,15 @@ -- | /O(d)/ Delete a single item from the 'BitSet'. Preserves order of 'null' and 'size' delete :: Enum a => a -> BitSet a -> BitSet a-delete x r@(BS a b c l h m u) +delete x r@(BS a b c l h m u _) | m < 0, e < l = bs (a+1) (b+1) (c+1) e h (shiftL m (l - e) .&. Bits.complement 1) u | m < 0, e > h = bs (a+1) (b+1) (c+1) l p (clearBit m p) u- | e < l = r- | e > h = r- | testBit m p = bs (a-1) (b-1) (c-1) l h (clearBit m p) u- | otherwise = r+ | b == 0 = r+ | a == -1 = pseudoComplement (singleton x) u+ | e < l = r+ | e > h = r+ | testBit m p = bs (a-1) (b-1) (c-1) l h (clearBit m p) u+ | otherwise = r where e = fromEnum x p = e - l@@ -182,7 +199,7 @@ -- | /O(1)/ Test for membership in a 'BitSet' member :: Enum a => a -> BitSet a -> Bool-member x (BS _ _ _ l h m _) +member x (BS _ _ _ l h m _ _) | e < l = m < 0 | e > h = m > 0 | otherwise = testBit m (e - l)@@ -193,90 +210,100 @@ -- | /O(d)/ convert to an Integer representation. Discards negative elements toInteger :: BitSet a -> Integer toInteger x = mantissa x `shift` exponent x+{-# INLINE toInteger #-} --- | /O(d)/. May force 'size' to take /O(d)/ if ranges overlap, preserves order of 'null'-union :: BitSet a -> BitSet a -> BitSet a -union x@(BS a b c l h m u) y@(BS a' b' c' l' h' m' u')+-- | /O(d)/.+union :: Enum a => BitSet a -> BitSet a -> BitSet a +union x@(BS a b c l h m u f) y@(BS a' b' c' l' h' m' u' _) | l' < l = union y x -- ensure left side has lower exponent | b == 0 = y -- fast empty union | b' == 0 = x -- fast empty union | a == -1 = entire u -- fast full union, recomplement obligation met by negative size | a' == -1 = entire u' -- fast full union, recomplement obligation met by negative size | m < 0, m' < 0 = recomplement (intersection (recomplement x) (recomplement y)) -- appeal to intersection, recomplement obligation met by 2s complement- | m' < 0 = recomplement (pseudoDiff (recomplement y) x u') -- union with complement, recomplement obligation met by 2s complement- | m < 0 = recomplement (pseudoDiff (recomplement x) y u) -- union with complement, recomplement obligation met by 2s complement+ | m' < 0 = recomplement (diff (recomplement y) x u') -- union with complement, recomplement obligation met by 2s complement+ | m < 0 = recomplement (diff (recomplement x) y u) -- union with complement, recomplement obligation met by 2s complement | h < l' = bs (a + a') (b + b') (c + c') l h' m'' u -- disjoint positive ranges | otherwise = bs (a `max` a') (b + b') (recount m'') l (h `max` h') m'' u -- overlapped positives where m'' = m .|. shiftL m' (l' - l)- entire = BS (-1) (-1) (-1) 0 0 (-1)+ entire u'' = BS (-1) (-1) (-1) 0 0 (-1) u'' f --- | /O(1)/ check to see if we are represented as a complemented 'BitSet'. -isComplemented :: BitSet a -> Bool+-- | /O(1)/ Check to see if we are represented as a complemented 'BitSet'. +isComplemented :: Enum a => BitSet a -> Bool isComplemented = (<0) . mantissa +{-# INLINE isComplemented #-} --- | /O(d)/. May force 'size' and 'null' both to take /O(d)/.-intersection :: BitSet a -> BitSet a -> BitSet a -intersection x@(BS a b _ l h m u) y@(BS a' b' _ l' h' m' u')+-- | /O(d)/ +intersection :: Enum a => BitSet a -> BitSet a -> BitSet a +intersection x@(BS a b _ l h m u _) y@(BS a' b' _ l' h' m' u' _) | l' < l = intersection y x | b == 0 = empty | b' == 0 = empty | a == -1 = y | a' == -1 = x | m < 0, m' < 0 = recomplement (union (recomplement x) (recomplement y))- | m' < 0 = pseudoDiff x (recomplement y) u'- | m < 0 = pseudoDiff y (recomplement x) u+ | m' < 0 = diff x (recomplement y) u'+ | m < 0 = diff y (recomplement x) u | h < l' = empty | otherwise = bs 0 (b `min` b') (recount m'') l'' (h `min` h') m'' u where l'' = max l l' m'' = shift m (l'' - l) .&. shift m' (l'' - l') --- | Unsafe internal method for computing differences in a particular universe of discourse--- preconditions:--- m >= 0, m' >= 0, a /= -1, a' /= -1, b /= 0, b' /= 0, u'' is the universe of discourse-pseudoDiff :: BitSet a -> BitSet a -> (Int,Int) -> BitSet a -pseudoDiff x@(BS a _ _ l h m _) (BS _ b' _ l' h' m' _) u''+-- | Unsafe internal method for computing differences in a known universe of discourse.+--+-- Preconditions:+--+-- (1) @m >= 0@+-- 2 @m' >= 0@+-- 3 @a /= -1@+-- 4 @a' /= -1@+-- 5 @b /= 0@+-- 6 @b' /= 0@+-- 7 @u''@ is a previously obtained copy of @(fromEnum minBound, fromEnum maxBound)@+--+diff :: Enum a => BitSet a -> BitSet a -> (Int,Int) -> BitSet a +diff x@(BS a _ _ l h m _ _) (BS _ b' _ l' h' m' _ _) u'' | h < l' = x | h' < l = x | otherwise = bs (max (a - b') 0) a (recount m'') l h m'' u'' where m'' = m .&. shift (Bits.complement m') (l' - l)+{-# INLINE diff #-} --- | /O(d)/. Preserves order of 'null'. May force /O(d)/ 'size'.+-- | /O(d)/ Remove all elements present in the second bitset from the first difference :: Enum a => BitSet a -> BitSet a -> BitSet a -difference x@(BS a b _ _ _ m u) y@(BS a' b' _ _ _ m' _) +difference x@(BS a b _ _ _ m u _) y@(BS a' b' _ _ _ m' _ _) | a == -1 = pseudoComplement y u | a' == -1 = empty | b == 0 = empty | b' == 0 = x- | m < 0, m' < 0 = pseudoDiff (recomplement y) (recomplement x) u+ | m < 0, m' < 0 = diff (recomplement y) (recomplement x) u | m < 0 = pseudoComplement (recomplement x `union` y) u | m' < 0 = x `union` recomplement y - | otherwise = pseudoDiff x y u+ | otherwise = diff x y u --- | /O(d)/. Preserves order of 'null'. May force /O(d)/ 'size'.+-- | /O(d)/ Infix 'difference' (\\) :: Enum a => BitSet a -> BitSet a -> BitSet a (\\) = difference+{-# INLINE (\\) #-} instance Eq (BitSet a) where- x@(BS _ _ _ l _ m u) == y@(BS _ _ _ l' _ m' _)- | signum m == signum m' = shift m (l - l'') == shift m' (l - l'') - | m' < 0 = y == x- | otherwise = mask .&. shift m (l - ul) == shift m' (l - ul)+ x@(BS _ _ _ l _ m u _) == y@(BS _ _ _ l' _ m' _ _)+ | signum m == signum m' = shift m (l - l'') == shift m' (l' - l'') + | m' < 0 = y == x+ | otherwise = mask .&. shift m (l - ul) == shift m' (l - ul) where l'' = min l l' mask = setBit 0 (uh - ul + 1) - 1 ul = fst u uh = snd u --- instance Ord (BitSet a) where--- BS _ _ _ l _ m _ `compare` BS _ _ _ l' _ m' _ = shift m (l'' - l) `compare` shift m' (l'' - l) where l'' = min l l'- instance (Enum a, Bounded a) => Bounded (BitSet a) where minBound = empty maxBound = result where- result = BS n n n l h m (l,h)+ result = BS n n n l h m (l,h) toEnum n = h - l + 1 l = fromEnum (minBound `asArgTypeOf` result) h = fromEnum (maxBound `asArgTypeOf` result)@@ -315,13 +342,14 @@ -- then scan the powers for the highest set bit scan :: Int -> Int -> Int scan !l !h- | l == h = l+ | l == h = l | bit (m+1) > n = scan l m- | otherwise = scan (m+1) h- where m = l + (h - l) `div` 2+ | otherwise = scan (m+1) h+ where + m = l + (h - l) `div` 2 -instance (Enum a, Show a) => Show (BitSet a) where- showsPrec d x@(BS _ _ _ _ _ m u)+instance Show a => Show (BitSet a) where+ showsPrec d x@(BS _ _ _ _ _ m u _) | m < 0 = showParen (d > 10) $ showString "pseudoComplement " . showsPrec 11 (recomplement x) . showString " " . showsPrec 11 u | otherwise = showParen (d > 10) $ showString "fromDistinctAscList " . showsPrec 11 (toList x) @@ -337,17 +365,25 @@ -- note that operations on values generated by toEnum are pretty slow because the bounds are suboptimal instance (Enum a, Bounded a) => Enum (BitSet a) where- fromEnum b@(BS _ _ _ l _ m _) = fromInteger (shiftL m (l - l'))+ fromEnum b@(BS _ _ _ l _ m _ _) = fromInteger (shiftL m (l - l')) where l' = fromEnum (minBound `asArgTypeOf` b) toEnum i = result where- result = BS a i (recount m) l h m undefined -- n <= 2^n, so i serves as a valid upper bound+ result = BS a i (recount m) l h m undefined toEnum -- n <= 2^n, so i serves as a valid upper bound l = fromEnum (minBound `asArgTypeOf` result) h = fromEnum (maxBound `asArgTypeOf` result) m = fromIntegral i a | m /= 0 = 1 -- allow a fast null check, but not much else | otherwise = 0++instance Foldable BitSet where+ fold = fold . toList+ foldMap f = foldMap f . toList+ foldr f z = foldr f z . toList+ foldl f z = foldl f z . toList+ foldr1 f = foldr1 f . toList+ foldl1 f = foldl1 f . toList instance Enum a => Monoid (BitSet a) where mempty = empty@@ -362,6 +398,7 @@ one = full times = intersection +instance (Bounded a, Enum a) => Ringoid (BitSet a) instance (Bounded a, Enum a) => LeftSemiNearRing (BitSet a) instance (Bounded a, Enum a) => RightSemiNearRing (BitSet a) instance (Bounded a, Enum a) => SemiRing (BitSet a)@@ -379,8 +416,8 @@ instance (Bounded a, Enum a) => RightModule (BitSet a) (BitSet a) where (.*) = times instance (Bounded a, Enum a) => Module (BitSet a) (BitSet a) -instance (Bounded a, Enum a) => Algebra Natural (BitSet a)+instance (Bounded a, Enum a) => RAlgebra Natural (BitSet a) -instance Enum a => Generator (BitSet a) where+instance Generator (BitSet a) where type Elem (BitSet a) = a mapReduce f = mapReduce f . toList
+ Data/Ring/Semi/Kleene.hs view
@@ -0,0 +1,10 @@+module Data.Ring.Semi.Kleene + ( module Data.Ring.Semi+ , KleeneAlgebra+ , star+ ) where++import Data.Ring.Semi++class SemiRing r => KleeneAlgebra r where+ star :: r -> r
Data/Ring/Semi/Natural.hs view
@@ -96,6 +96,7 @@ one = 1 times = (*) +instance Ringoid Natural instance LeftSemiNearRing Natural instance RightSemiNearRing Natural instance SemiRing Natural
Data/Ring/Semi/Near.hs view
@@ -19,6 +19,7 @@ module Data.Ring.Semi.Near ( module Data.Monoid.Multiplicative+ , Ringoid , LeftSemiNearRing , RightSemiNearRing ) where@@ -45,50 +46,48 @@ import Text.Parsec.Prim --- | @a * (b + c) = (a * b) + (a * c)@-class (Multiplicative m, Monoid m) => LeftSemiNearRing m +-- | @0@ annihilates `times`+class (Multiplicative m, Monoid m) => Ringoid m+instance Ringoid m => Ringoid (Self m)+instance Ringoid m => Ringoid (FromString m)+instance Ringoid m => Ringoid (ReducedBy m s)+instance Ringoid m => Ringoid (Dual m)+instance (Measured v m, Monoid m) => Ringoid (FingerTree v m)+instance Monoid m => Ringoid [m]+instance Monoid m => Ringoid (Maybe m)+instance Monoid m => Ringoid (Seq m)+instance (Stream s m t, Monoid a) => Ringoid (ParsecT s u m a)+instance (MonadPlus m, Monoid n) => Ringoid (SState.StateT s m n)+instance (MonadPlus m, Monoid n) => Ringoid (LState.StateT s m n)+instance (MonadPlus m, Monoid n) => Ringoid (ReaderT e m n)+instance (MonadPlus m, Monoid w, Monoid n) => Ringoid (SRWS.RWST r w s m n)+instance (MonadPlus m, Monoid w, Monoid n) => Ringoid (LRWS.RWST r w s m n)+instance (MonadPlus m, Monoid w, Monoid n) => Ringoid (SWriter.WriterT w m n)+instance (MonadPlus m, Monoid w, Monoid n) => Ringoid (LWriter.WriterT w m n) --- 'Monoid' transformers+-- | @a * (b + c) = (a * b) + (a * c)@+class Ringoid m => LeftSemiNearRing m instance LeftSemiNearRing m => LeftSemiNearRing (Self m) instance LeftSemiNearRing m => LeftSemiNearRing (FromString m) instance LeftSemiNearRing m => LeftSemiNearRing (ReducedBy m s) instance RightSemiNearRing m => LeftSemiNearRing (Dual m) -- | @(a + b) * c = (a * c) + (b * c)@-class (Multiplicative m, Monoid m) => RightSemiNearRing m ---- 'Monoid' transformers+class Ringoid m => RightSemiNearRing m instance RightSemiNearRing m => RightSemiNearRing (Self m) instance RightSemiNearRing m => RightSemiNearRing (FromString m) instance RightSemiNearRing m => RightSemiNearRing (ReducedBy m s) instance LeftSemiNearRing m => RightSemiNearRing (Dual m)---- non-'Monad' instances instance (Measured v m, Monoid m) => RightSemiNearRing (FingerTree v m)---- 'Monad' instances--- Every 'MonadPlus' over a 'Monoid' with an appropriate 'Multiplicative' instance--- for 'liftM2 mappend' is a 'RightSemiNearRing' by 'MonadPlus' left-distributivity- instance Monoid m => RightSemiNearRing [m]- instance Monoid m => RightSemiNearRing (Maybe m)- instance Monoid m => RightSemiNearRing (Seq m)- instance (Stream s m t, Monoid a) => RightSemiNearRing (ParsecT s u m a)- instance (MonadPlus m, Monoid n) => RightSemiNearRing (SState.StateT s m n)- instance (MonadPlus m, Monoid n) => RightSemiNearRing (LState.StateT s m n)- instance (MonadPlus m, Monoid n) => RightSemiNearRing (ReaderT e m n)- instance (MonadPlus m, Monoid w, Monoid n) => RightSemiNearRing (SRWS.RWST r w s m n)- instance (MonadPlus m, Monoid w, Monoid n) => RightSemiNearRing (LRWS.RWST r w s m n)- instance (MonadPlus m, Monoid w, Monoid n) => RightSemiNearRing (SWriter.WriterT w m n)- instance (MonadPlus m, Monoid w, Monoid n) => RightSemiNearRing (LWriter.WriterT w m n)
Data/Ring/Semi/Ord.hs view
@@ -35,6 +35,7 @@ times = min one = maxBound +instance (Bounded a, Ord a) => Ringoid (Order a) instance (Bounded a, Ord a) => RightSemiNearRing (Order a) instance (Bounded a, Ord a) => LeftSemiNearRing (Order a) instance (Bounded a, Ord a) => SemiRing (Order a)@@ -98,6 +99,7 @@ times = min one = maxBound +instance Ord a => Ringoid (Priority a) instance Ord a => LeftSemiNearRing (Priority a) instance Ord a => RightSemiNearRing (Priority a) instance Ord a => SemiRing (Priority a)
Data/Ring/Semi/Tropical.hs view
@@ -68,6 +68,7 @@ Tropical (Just a) `times` Tropical (Just b) = point (a + b) _ `times` Tropical Nothing = infinity +instance (Ord a, Num a) => Ringoid (Tropical a) instance (Ord a, Num a) => LeftSemiNearRing (Tropical a) instance (Ord a, Num a) => RightSemiNearRing (Tropical a) instance (Ord a, Num a) => SemiRing (Tropical a)
+ Data/Set/Unboxed.hs view
@@ -0,0 +1,1258 @@+{-# LANGUAGE TypeFamilies, CPP, ViewPatterns #-}++{------------------------------------------------------------------------------+-- |+-- Module : Data.Set.Unboxed+-- Copyright : (c) Edward Kmett 2009+-- (c) Daan Leijen 2002+-- License : BSD-style+-- Maintainer : ekmett@gmail.com+-- Stability : experimental+-- Portability : non-portable (type families, view patterns)+--+-- An efficient implementation of sets.+--+-- Since many function names (but not the type name) clash with+-- "Prelude" names, this module is usually imported @qualified@, e.g.+--+-- > import Data.Set.Unboxed (USet)+-- > import qualified Data.Set.Unboxed as USet+--+-- The implementation of 'USet' is based on /size balanced/ binary trees (or+-- trees of /bounded balance/) as described by:+--+-- * Stephen Adams, \"/Efficient sets: a balancing act/\",+-- Journal of Functional Programming 3(4):553-562, October 1993,+-- <http://www.swiss.ai.mit.edu/~adams/BB/>.+--+-- * J. Nievergelt and E.M. Reingold,+-- \"/Binary search trees of bounded balance/\",+-- SIAM journal of computing 2(1), March 1973.+--+-- Note that the implementation is /left-biased/ -- the elements of a+-- first argument are always preferred to the second, for example in+-- 'union' or 'insert'. Of course, left-biasing can only be observed+-- when equality is an equivalence relation instead of structural+-- equality.+--+-- Modified from "Data.Set" to use type families for automatic boxing.+-----------------------------------------------------------------------------+-}++module Data.Set.Unboxed ( + -- * Set type+ USet -- instance Eq,Ord,Show,Read,Data,Typeable+ , US++ -- * Operators+ , (\\)++ -- * Query+ , null+ , size+ , member+ , notMember+ , isSubsetOf+ , isProperSubsetOf+ + -- * Construction+ , empty+ , singleton+ , insert+ , delete+ + -- * Combine+ , union, unions+ , difference+ , intersection+ + -- * Filter+ , filter+ , partition+ , split+ , splitMember++ -- * Map+ , map+ , mapMonotonic++ -- * Fold+ , fold++ -- * Min\/Max+ , findMin+ , findMax+ , deleteMin+ , deleteMax+ , deleteFindMin+ , deleteFindMax+ , maxView+ , minView++ -- * Conversion++ -- ** List+ , elems+ , toList+ , fromList+ + -- ** Ordered list+ , toAscList+ , fromAscList+ , fromDistinctAscList+ + -- * Debugging+ , showTree+ , showTreeWith+ , valid+ ) where++import Prelude hiding (filter,foldr,null,map)+import qualified Data.List as List+import Data.Monoid (Monoid(..))+import Data.Generator.Combinators (Generator,Elem,foldMap, mapReduce)+#ifndef __GLASGOW_HASKELL__+import Data.Typeable (Typeable, typeOf, typeOfDefault)+#endif+import Data.Typeable (Typeable1(..), TyCon, mkTyCon, mkTyConApp)+import Data.Word+import Data.Int++{-+-- just for testing+import Test.QuickCheck +import Data.List (nub,sort)+import qualified Data.List as List+-}++#if __GLASGOW_HASKELL__+import Text.Read+import Data.Data (Data(..), mkNorepType, gcast1)+#endif++{--------------------------------------------------------------------+ Operators+--------------------------------------------------------------------}+infixl 9 \\ --++-- | /O(n+m)/. See 'difference'.+(\\) :: (US a, Ord a) => USet a -> USet a -> USet a+m1 \\ m2 = difference m1 m2++{--------------------------------------------------------------------+ Sets are size balanced trees+--------------------------------------------------------------------}+type Size = Int++-- | A set of values @a@.+data Set a = Tip + | Bin {-# UNPACK #-} !Size a !(USet a) !(USet a) ++-- smart unboxed types+class US a where+ data USet a+ view :: USet a -> Set a+ {-# INLINE view #-}+ tip :: USet a+ {-# INLINE tip #-}+ bin :: Size -> a -> USet a -> USet a -> USet a+ {-# INLINE bin #-}+++instance (US a, Ord a) => Monoid (USet a) where+ mempty = empty+ mappend = union+ mconcat = unions++{-+instance US a => Generator (USet a) where+ type Elem (USet a) = a+ mapReduce _ (view -> Tip) = mempty+ mapReduce f (view -> Bin _s k l r) = mapReduce f l `mappend` f k `mappend` mapReduce f r+-}++#if __GLASGOW_HASKELL__++{--------------------------------------------------------------------+ A Data instance +--------------------------------------------------------------------}++-- This instance preserves data abstraction at the cost of inefficiency.+-- We omit reflection services for the sake of data abstraction.++{-+instance (US a, Data a, Ord a) => Data (USet a) where+ gfoldl f z set = z fromList `f` (toList set)+ toConstr _ = error "toConstr"+ gunfold _ _ = error "gunfold"+ dataTypeOf _ = mkNorepType "Data.Set.Set"+ dataCast1 f = gcast1 f+-}++#endif++{--------------------------------------------------------------------+ Query+--------------------------------------------------------------------}+-- | /O(1)/. Is this the empty set?+null :: US a => USet a -> Bool+null (view -> Tip) = True+null (view -> Bin {}) = False++-- | /O(1)/. The number of elements in the set.+size :: US a => USet a -> Int+size (view -> Tip) = 0+size (view -> Bin sz _ _ _) = sz++-- | /O(log n)/. Is the element in the set?+member :: (US a, Ord a) => a -> USet a -> Bool+member x (view -> Tip) = False+member x (view -> Bin _ y l r) = + case compare x y of+ LT -> member x l+ GT -> member x r+ EQ -> True ++-- | /O(log n)/. Is the element not in the set?+notMember :: (US a, Ord a) => a -> USet a -> Bool+notMember x t = not $ member x t++{--------------------------------------------------------------------+ Construction+--------------------------------------------------------------------}+-- | /O(1)/. The empty set.+empty :: US a => USet a+empty = tip++-- | /O(1)/. Create a singleton set.+singleton :: US a => a -> USet a+singleton x = bin 1 x tip tip++{--------------------------------------------------------------------+ Insertion, Deletion+--------------------------------------------------------------------}+-- | /O(log n)/. Insert an element in a set.+-- If the set already contains an element equal to the given value,+-- it is replaced with the new value.+insert :: (US a, Ord a) => a -> USet a -> USet a+insert x (view -> Tip) = singleton x+insert x (view -> Bin sz y l r) = case compare x y of+ LT -> balance y (insert x l) r+ GT -> balance y l (insert x r)+ EQ -> bin sz x l r++-- | /O(log n)/. Delete an element from a set.+delete :: (US a, Ord a) => a -> USet a -> USet a+delete x (view -> Tip) = tip+delete x (view -> Bin _ y l r) = case compare x y of+ LT -> balance y (delete x l) r+ GT -> balance y l (delete x r)+ EQ -> glue l r++{--------------------------------------------------------------------+ Subset+--------------------------------------------------------------------}+-- | /O(n+m)/. Is this a proper subset? (ie. a subset but not equal).+isProperSubsetOf :: (US a, Ord a) => USet a -> USet a -> Bool+isProperSubsetOf s1 s2+ = (size s1 < size s2) && (isSubsetOf s1 s2)++-- | /O(n+m)/. Is this a subset?+-- @(s1 `isSubsetOf` s2)@ tells whether @s1@ is a subset of @s2@.+isSubsetOf :: (US a, Ord a) => USet a -> USet a -> Bool+isSubsetOf t1 t2 = (size t1 <= size t2) && (isSubsetOfX t1 t2)++isSubsetOfX :: (US a, Ord a) => USet a -> USet a -> Bool+isSubsetOfX (view -> Tip) _ = True+isSubsetOfX _ (view -> Tip) = False+isSubsetOfX (view -> Bin _ x l r) t = found && isSubsetOfX l lt && isSubsetOfX r gt+ where+ (lt,found,gt) = splitMember x t+++{--------------------------------------------------------------------+ Minimal, Maximal+--------------------------------------------------------------------}+-- | /O(log n)/. The minimal element of a set.+findMin :: US a => USet a -> a+findMin (view -> Bin _ x (view -> Tip) _) = x+findMin (view -> Bin _ _ l _) = findMin l+findMin (view -> Tip) = error "Set.findMin: empty set has no minimal element"++-- | /O(log n)/. The maximal element of a set.+findMax :: US a => USet a -> a+findMax (view -> Bin _ x _ (view -> Tip)) = x+findMax (view -> Bin _ _ _ r) = findMax r+findMax (view -> Tip) = error "Set.findMax: empty set has no maximal element"++-- | /O(log n)/. Delete the minimal element.+deleteMin :: US a => USet a -> USet a+deleteMin (view -> Bin _ _ (view -> Tip) r) = r+deleteMin (view -> Bin _ x l r) = balance x (deleteMin l) r+deleteMin (view -> Tip) = tip++-- | /O(log n)/. Delete the maximal element.+deleteMax :: US a => USet a -> USet a+deleteMax (view -> Bin _ _ l (view -> Tip)) = l+deleteMax (view -> Bin _ x l r) = balance x l (deleteMax r)+deleteMax (view -> Tip) = tip++{--------------------------------------------------------------------+ Union. +--------------------------------------------------------------------}+-- | The union of a list of sets: (@'unions' == 'foldl' 'union' 'empty'@).+unions :: (US a, Ord a) => [USet a] -> USet a+unions ts+ = foldlStrict union empty ts+++-- | /O(n+m)/. The union of two sets, preferring the first set when+-- equal elements are encountered.+-- The implementation uses the efficient /hedge-union/ algorithm.+-- Hedge-union is more efficient on (bigset `union` smallset).+union :: (US a, Ord a) => USet a -> USet a -> USet a+union (view -> Tip) t2 = t2+union t1 (view -> Tip) = t1+union t1 t2 = hedgeUnion (const LT) (const GT) t1 t2++hedgeUnion :: (US a, Ord a) => (a -> Ordering) -> (a -> Ordering) -> USet a -> USet a -> USet a+hedgeUnion _ _ t1 (view -> Tip) = t1+hedgeUnion cmplo cmphi (view -> Tip) (view -> Bin _ x l r) = join x (filterGt cmplo l) (filterLt cmphi r)+hedgeUnion cmplo cmphi (view -> Bin _ x l r) t2 = join x (hedgeUnion cmplo cmpx l (trim cmplo cmpx t2)) (hedgeUnion cmpx cmphi r (trim cmpx cmphi t2))+ where+ cmpx = compare x++{--------------------------------------------------------------------+ Difference+--------------------------------------------------------------------}+-- | /O(n+m)/. Difference of two sets. +-- The implementation uses an efficient /hedge/ algorithm comparable with /hedge-union/.+difference :: (US a, Ord a) => USet a -> USet a -> USet a+difference (view -> Tip) _ = tip+difference t1 (view -> Tip) = t1+difference t1 t2 = hedgeDiff (const LT) (const GT) t1 t2++hedgeDiff :: (US a, Ord a) => (a -> Ordering) -> (a -> Ordering) -> USet a -> USet a -> USet a+hedgeDiff _ _ (view -> Tip) _ = tip+hedgeDiff cmplo cmphi (view -> Bin _ x l r) (view -> Tip) = join x (filterGt cmplo l) (filterLt cmphi r)+hedgeDiff cmplo cmphi t (view -> Bin _ x l r) = merge (hedgeDiff cmplo cmpx (trim cmplo cmpx t) l) (hedgeDiff cmpx cmphi (trim cmpx cmphi t) r)+ where+ cmpx = compare x++{--------------------------------------------------------------------+ Intersection+--------------------------------------------------------------------}+-- | /O(n+m)/. The intersection of two sets.+-- Elements of the result come from the first set, so for example+--+-- > import qualified Data.Set as S+-- > data AB = A | B deriving Show+-- > instance Ord AB where compare _ _ = EQ+-- > instance Eq AB where _ == _ = True+-- > main = print (S.singleton A `S.intersection` S.singleton B,+-- > S.singleton B `S.intersection` S.singleton A)+--+-- prints @(fromList [A],fromList [B])@.+intersection :: (US a, Ord a) => USet a -> USet a -> USet a+intersection (view -> Tip) _ = tip+intersection _ (view -> Tip) = tip+intersection t1@(view -> Bin s1 x1 l1 r1) t2@(view -> Bin s2 x2 l2 r2) =+ if s1 >= s2 then+ let (lt,found,gt) = splitLookup x2 t1+ tl = intersection lt l2+ tr = intersection gt r2+ in case found of+ Just x -> join x tl tr+ Nothing -> merge tl tr+ else let (lt,found,gt) = splitMember x1 t2+ tl = intersection l1 lt+ tr = intersection r1 gt+ in if found then join x1 tl tr+ else merge tl tr++{--------------------------------------------------------------------+ Filter and partition+--------------------------------------------------------------------}+-- | /O(n)/. Filter all elements that satisfy the predicate.+filter :: (US a, Ord a) => (a -> Bool) -> USet a -> USet a+filter _ (view -> Tip) = tip+filter p (view -> Bin _ x l r)+ | p x = join x (filter p l) (filter p r)+ | otherwise = merge (filter p l) (filter p r)++-- | /O(n)/. Partition the set into two sets, one with all elements that satisfy+-- the predicate and one with all elements that don't satisfy the predicate.+-- See also 'split'.+partition :: (US a, Ord a) => (a -> Bool) -> USet a -> (USet a,USet a)+partition _ (view -> Tip) = (tip,tip)+partition p (view -> Bin _ x l r)+ | p x = (join x l1 r1,merge l2 r2)+ | otherwise = (merge l1 r1,join x l2 r2)+ where+ (l1,l2) = partition p l+ (r1,r2) = partition p r++{----------------------------------------------------------------------+ Map+----------------------------------------------------------------------}++-- | /O(n*log n)/. +-- @'map' f s@ is the set obtained by applying @f@ to each element of @s@.+-- +-- It's worth noting that the size of the result may be smaller if,+-- for some @(x,y)@, @x \/= y && f x == f y@++map :: (US a, US b, Ord a, Ord b) => (a->b) -> USet a -> USet b+map f = fromList . List.map f . toList++-- | /O(n)/. The +--+-- @'mapMonotonic' f s == 'map' f s@, but works only when @f@ is monotonic.+-- /The precondition is not checked./+-- Semi-formally, we have:+-- +-- > and [x < y ==> f x < f y | x <- ls, y <- ls] +-- > ==> mapMonotonic f s == map f s+-- > where ls = toList s++mapMonotonic :: (US a, US b) => (a->b) -> USet a -> USet b+mapMonotonic _ (view -> Tip) = tip+mapMonotonic f (view -> Bin sz x l r) = bin sz (f x) (mapMonotonic f l) (mapMonotonic f r)+++{--------------------------------------------------------------------+ Fold+--------------------------------------------------------------------}+-- | /O(n)/. Fold over the elements of a set in an unspecified order.+fold :: US a => (a -> b -> b) -> b -> USet a -> b+fold f z s = foldr f z s++-- | /O(n)/. Post-order fold.+foldr :: US a => (a -> b -> b) -> b -> USet a -> b+foldr _ z (view -> Tip) = z+foldr f z (view -> Bin _ x l r) = foldr f (f x (foldr f z r)) l++{--------------------------------------------------------------------+ List variations +--------------------------------------------------------------------}+-- | /O(n)/. The elements of a set.+elems :: US a => USet a -> [a]+elems = toList++{--------------------------------------------------------------------+ Lists +--------------------------------------------------------------------}+-- | /O(n)/. Convert the set to a list of elements.+toList :: US a => USet a -> [a]+toList = toAscList++-- | /O(n)/. Convert the set to an ascending list of elements.+toAscList :: US a => USet a -> [a]+toAscList = foldr (:) []+++-- | /O(n*log n)/. Create a set from a list of elements.+fromList :: (US a, Ord a) => [a] -> USet a +fromList = foldlStrict ins empty+ where+ ins t x = insert x t++{--------------------------------------------------------------------+ Building trees from ascending/descending lists can be done in linear time.+ + Note that if [xs] is ascending that: + fromAscList xs == fromList xs+--------------------------------------------------------------------}+-- | /O(n)/. Build a set from an ascending list in linear time.+-- /The precondition (input list is ascending) is not checked./+fromAscList :: (US a, Eq a) => [a] -> USet 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'+++-- | /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./+fromDistinctAscList :: US a => [a] -> USet a +fromDistinctAscList xs+ = build const (length xs) xs+ where+ -- 1) use continutations so that we use heap space instead of stack space.+ -- 2) special case for n==5 to build bushier trees. + build c 0 xs' = c tip xs'+ build c 5 xs' = case xs' of+ (x1:x2:x3:x4:x5:xx) + -> c (bin_ x4 (bin_ x2 (singleton x1) (singleton x3)) (singleton x5)) xx+ _ -> error "fromDistinctAscList build 5"+ build c n xs' = seq nr $ build (buildR nr c) nl xs'+ where+ nl = n `div` 2+ nr = n - nl - 1++ buildR n c l (x:ys) = build (buildB l x c) n ys+ buildR _ _ _ [] = error "fromDistinctAscList buildR []"+ buildB l x c r zs = c (bin_ x l r) zs++{--------------------------------------------------------------------+ Eq converts the set to a list. In a lazy setting, this + actually seems one of the faster methods to compare two trees + and it is certainly the simplest :-)+--------------------------------------------------------------------}+instance (US a, Eq a) => Eq (USet a) where+ t1 == t2 = (size t1 == size t2) && (toAscList t1 == toAscList t2)++{--------------------------------------------------------------------+ Ord +--------------------------------------------------------------------}++instance (US a, Ord a) => Ord (USet a) where+ compare s1 s2 = compare (toAscList s1) (toAscList s2) ++{--------------------------------------------------------------------+ Show+--------------------------------------------------------------------}+instance (US a, Show a) => Show (USet a) where+ showsPrec p xs = showParen (p > 10) $+ showString "fromList " . shows (toList xs)++{-+XXX unused code++showSet :: (Show a) => [a] -> ShowS+showSet [] + = showString "{}" +showSet (x:xs) + = showChar '{' . shows x . showTail xs+ where+ showTail [] = showChar '}'+ showTail (x':xs') = showChar ',' . shows x' . showTail xs'+-}++{--------------------------------------------------------------------+ Read+--------------------------------------------------------------------}+instance (US a, Read a, Ord a) => Read (USet a) where+#ifdef __GLASGOW_HASKELL__+ readPrec = parens $ prec 10 $ do+ Ident "fromList" <- lexP+ xs <- readPrec+ return (fromList xs)++ readListPrec = readListPrecDefault+#else+ readsPrec p = readParen (p > 10) $ \ r -> do+ ("fromList",s) <- lex r+ (xs,t) <- reads s+ return (fromList xs,t)+#endif++{--------------------------------------------------------------------+ Typeable/Data+--------------------------------------------------------------------}++-- #include "Typeable.h"+-- INSTANCE_TYPEABLE1(Set,setTc,"Set")++{--------------------------------------------------------------------+ Utility functions that return sub-ranges of the original+ tree. Some functions take a comparison function as argument to+ allow comparisons against infinite values. A function [cmplo x]+ should be read as [compare lo x].++ [trim cmplo cmphi t] A tree that is either empty or where [cmplo x == LT]+ and [cmphi x == GT] for the value [x] of the root.+ [filterGt cmp t] A tree where for all values [k]. [cmp k == LT]+ [filterLt cmp t] A tree where for all values [k]. [cmp k == GT]++ [split k t] Returns two trees [l] and [r] where all values+ in [l] are <[k] and all keys in [r] are >[k].+ [splitMember k t] Just like [split] but also returns whether [k]+ was found in the tree.+--------------------------------------------------------------------}++{--------------------------------------------------------------------+ [trim lo hi t] trims away all subtrees that surely contain no+ values between the range [lo] to [hi]. The returned tree is either+ empty or the key of the root is between @lo@ and @hi@.+--------------------------------------------------------------------}+trim :: US a => (a -> Ordering) -> (a -> Ordering) -> USet a -> USet a+trim _ _ (view -> Tip) = tip+trim cmplo cmphi t@(view -> Bin _ x l r)+ = case cmplo x of+ LT -> case cmphi x of+ GT -> t+ _ -> trim cmplo cmphi l+ _ -> trim cmplo cmphi r++{--------------------------------------------------------------------+ [filterGt x t] filter all values >[x] from tree [t]+ [filterLt x t] filter all values <[x] from tree [t]+--------------------------------------------------------------------}+filterGt :: US a => (a -> Ordering) -> USet a -> USet a+filterGt _ (view -> Tip) = tip+filterGt cmp (view -> Bin _ x l r)+ = case cmp x of+ LT -> join x (filterGt cmp l) r+ GT -> filterGt cmp r+ EQ -> r+ +filterLt :: US a => (a -> Ordering) -> USet a -> USet a+filterLt _ (view -> Tip) = tip+filterLt cmp (view -> Bin _ x l r)+ = case cmp x of+ LT -> filterLt cmp l+ GT -> join x l (filterLt cmp r)+ EQ -> l+++{--------------------------------------------------------------------+ Split+--------------------------------------------------------------------}+-- | /O(log n)/. The expression (@'split' x set@) is a pair @(set1,set2)@+-- where @set1@ comprises the elements of @set@ less than @x@ and @set2@+-- comprises the elements of @set@ greater than @x@.+split :: (US a, Ord a) => a -> USet a -> (USet a,USet a)+split _ (view -> Tip) = (tip,tip)+split x (view -> Bin _ y l r)+ = case compare x y of+ LT -> let (lt,gt) = split x l in (lt,join y gt r)+ GT -> let (lt,gt) = split x r in (join y l lt,gt)+ EQ -> (l,r)++-- | /O(log n)/. Performs a 'split' but also returns whether the pivot+-- element was found in the original set.+splitMember :: (US a, Ord a) => a -> USet a -> (USet a,Bool,USet a)+splitMember x t = let (l,m,r) = splitLookup x t in+ (l,maybe False (const True) m,r)++-- | /O(log n)/. Performs a 'split' but also returns the pivot+-- element that was found in the original set.+splitLookup :: (US a, Ord a) => a -> USet a -> (USet a,Maybe a,USet a)+splitLookup _ (view -> Tip) = (tip,Nothing,tip)+splitLookup x (view -> Bin _ y l r)+ = case compare x y of+ LT -> let (lt,found,gt) = splitLookup x l in (lt,found,join y gt r)+ GT -> let (lt,found,gt) = splitLookup x r in (join y l lt,found,gt)+ EQ -> (l,Just y,r)++{--------------------------------------------------------------------+ Utility functions that maintain the balance properties of the tree.+ All constructors assume that all values in [l] < [x] and all values+ in [r] > [x], and that [l] and [r] are valid trees.+ + In order of sophistication:+ [Bin sz x l r] The type constructor.+ [bin_ x l r] Maintains the correct size, assumes that both [l]+ and [r] are balanced with respect to each other.+ [balance x l r] Restores the balance and size.+ Assumes that the original tree was balanced and+ that [l] or [r] has changed by at most one element.+ [join x l r] Restores balance and size. ++ Furthermore, we can construct a new tree from two trees. Both operations+ assume that all values in [l] < all values in [r] and that [l] and [r]+ are valid:+ [glue l r] Glues [l] and [r] together. Assumes that [l] and+ [r] are already balanced with respect to each other.+ [merge l r] Merges two trees and restores balance.++ Note: in contrast to Adam's paper, we use (<=) comparisons instead+ of (<) comparisons in [join], [merge] and [balance]. + Quickcheck (on [difference]) showed that this was necessary in order + to maintain the invariants. It is quite unsatisfactory that I haven't + been able to find out why this is actually the case! Fortunately, it + doesn't hurt to be a bit more conservative.+--------------------------------------------------------------------}++{--------------------------------------------------------------------+ Join +--------------------------------------------------------------------}+join :: US a => a -> USet a -> USet a -> USet a+join x (view -> Tip) r = insertMin x r+join x l (view -> Tip) = insertMax x l+join x l@(view -> Bin sizeL y ly ry) r@(view -> Bin sizeR z lz rz)+ | delta*sizeL <= sizeR = balance z (join x l lz) rz+ | delta*sizeR <= sizeL = balance y ly (join x ry r)+ | otherwise = bin_ x l r+++-- insertMin and insertMax don't perform potentially expensive comparisons.+insertMax,insertMin :: US a => a -> USet a -> USet a +insertMax x t+ = case view t of+ Tip -> singleton x+ Bin _ y l r+ -> balance y l (insertMax x r)+ +insertMin x t+ = case view t of+ Tip -> singleton x+ Bin _ y l r+ -> balance y (insertMin x l) r+ +{--------------------------------------------------------------------+ [merge l r]: merges two trees.+--------------------------------------------------------------------}+merge :: US a => USet a -> USet a -> USet a+merge (view -> Tip) r = r+merge l (view -> Tip) = l+merge l@(view -> Bin sizeL x lx rx) r@(view -> Bin sizeR y ly ry)+ | delta*sizeL <= sizeR = balance y (merge l ly) ry+ | delta*sizeR <= sizeL = balance x lx (merge rx r)+ | otherwise = glue l r++{--------------------------------------------------------------------+ [glue l r]: glues two trees together.+ Assumes that [l] and [r] are already balanced with respect to each other.+--------------------------------------------------------------------}+glue :: US a => USet a -> USet a -> USet a+glue (view -> Tip) r = r+glue l (view -> Tip) = l+glue l r + | size l > size r = let (m,l') = deleteFindMax l in balance m l' r+ | otherwise = let (m,r') = deleteFindMin r in balance m l r'+++-- | /O(log n)/. Delete and find the minimal element.+-- +-- > deleteFindMin set = (findMin set, deleteMin set)++deleteFindMin :: US a => USet a -> (a,USet a)+deleteFindMin t + = case view t of+ Bin _ x (view -> Tip) r -> (x,r)+ Bin _ x l r -> let (xm,l') = deleteFindMin l in (xm,balance x l' r)+ Tip -> (error "Set.deleteFindMin: can not return the minimal element of an empty set", tip)++-- | /O(log n)/. Delete and find the maximal element.+-- +-- > deleteFindMax set = (findMax set, deleteMax set)+deleteFindMax :: US a => USet a -> (a,USet a)+deleteFindMax t+ = case view t of+ Bin _ x l (view -> Tip) -> (x,l)+ Bin _ x l r -> let (xm,r') = deleteFindMax r in (xm,balance x l r')+ Tip -> (error "Set.deleteFindMax: can not return the maximal element of an empty set", tip)++-- | /O(log n)/. Retrieves the minimal key of the set, and the set+-- stripped of that element, or 'Nothing' if passed an empty set.+minView :: US a => USet a -> Maybe (a, USet a)+minView (view -> Tip) = Nothing+minView x = Just (deleteFindMin x)++-- | /O(log n)/. Retrieves the maximal key of the set, and the set+-- stripped of that element, or 'Nothing' if passed an empty set.+maxView :: US a => USet a -> Maybe (a, USet a)+maxView (view -> Tip) = Nothing+maxView x = Just (deleteFindMax x)++{--------------------------------------------------------------------+ [balance x l r] balances two trees with value x.+ The sizes of the trees should balance after decreasing the+ size of one of them. (a rotation).++ [delta] is the maximal relative difference between the sizes of+ two trees, it corresponds with the [w] in Adams' paper,+ or equivalently, [1/delta] corresponds with the $\alpha$+ in Nievergelt's paper. Adams shows that [delta] should+ be larger than 3.745 in order to garantee that the+ rotations can always restore balance. ++ [ratio] is the ratio between an outer and inner sibling of the+ heavier subtree in an unbalanced setting. It determines+ whether a double or single rotation should be performed+ to restore balance. It is correspondes with the inverse+ of $\alpha$ in Adam's article.++ Note that:+ - [delta] should be larger than 4.646 with a [ratio] of 2.+ - [delta] should be larger than 3.745 with a [ratio] of 1.534.+ + - A lower [delta] leads to a more 'perfectly' balanced tree.+ - A higher [delta] performs less rebalancing.++ - Balancing is automatic for random data and a balancing+ scheme is only necessary to avoid pathological worst cases.+ Almost any choice will do in practice+ + - Allthough it seems that a rather large [delta] may perform better + than smaller one, measurements have shown that the smallest [delta]+ of 4 is actually the fastest on a wide range of operations. It+ especially improves performance on worst-case scenarios like+ a sequence of ordered insertions.++ Note: in contrast to Adams' paper, we use a ratio of (at least) 2+ to decide whether a single or double rotation is needed. Allthough+ he actually proves that this ratio is needed to maintain the+ invariants, his implementation uses a (invalid) ratio of 1. + He is aware of the problem though since he has put a comment in his + original source code that he doesn't care about generating a + slightly inbalanced tree since it doesn't seem to matter in practice. + However (since we use quickcheck :-) we will stick to strictly balanced + trees.+--------------------------------------------------------------------}+delta,ratio :: Int+delta = 4+ratio = 2++balance :: US a => a -> USet a -> USet a -> USet a+balance x l r+ | sizeL + sizeR <= 1 = bin sizeX x l r+ | sizeR >= delta*sizeL = rotateL x l r+ | sizeL >= delta*sizeR = rotateR x l r+ | otherwise = bin sizeX x l r+ where+ sizeL = size l+ sizeR = size r+ sizeX = sizeL + sizeR + 1++-- rotate+rotateL :: US a => a -> USet a -> USet a -> USet a+rotateL x l r@(view -> Bin _ _ ly ry)+ | size ly < ratio*size ry = singleL x l r+ | otherwise = doubleL x l r+rotateL _ _ (view -> Tip) = error "rotateL Tip"++rotateR :: US a => a -> USet a -> USet a -> USet a+rotateR x l@(view -> Bin _ _ ly ry) r+ | size ry < ratio*size ly = singleR x l r+ | otherwise = doubleR x l r+rotateR _ (view -> Tip) _ = error "rotateL Tip"++-- basic rotations+singleL, singleR :: US a => a -> USet a -> USet a -> USet a+singleL x1 t1 (view -> Bin _ x2 t2 t3) = bin_ x2 (bin_ x1 t1 t2) t3+singleL _ _ (view -> Tip) = error "singleL"+singleR x1 (view -> Bin _ x2 t1 t2) t3 = bin_ x2 t1 (bin_ x1 t2 t3)+singleR _ (view -> Tip) _ = error "singleR"++doubleL, doubleR :: US a => a -> USet a -> USet a -> USet a+doubleL x1 t1 (view -> Bin _ x2 (view -> Bin _ x3 t2 t3) t4) = bin_ x3 (bin_ x1 t1 t2) (bin_ x2 t3 t4)+doubleL _ _ _ = error "doubleL"+doubleR x1 (view -> Bin _ x2 t1 (view -> Bin _ x3 t2 t3)) t4 = bin_ x3 (bin_ x2 t1 t2) (bin_ x1 t3 t4)+doubleR _ _ _ = error "doubleR"+++{--------------------------------------------------------------------+ The bin constructor maintains the size of the tree+--------------------------------------------------------------------}+bin_ :: US a => a -> USet a -> USet a -> USet a+bin_ x l r+ = bin (size l + size r + 1) x l r+++{--------------------------------------------------------------------+ Utilities+--------------------------------------------------------------------}+foldlStrict :: (a -> b -> a) -> a -> [b] -> a+foldlStrict f z xs+ = case xs of+ [] -> z+ (x:xx) -> let z' = f z x in seq z' (foldlStrict f z' xx)+++{--------------------------------------------------------------------+ Debugging+--------------------------------------------------------------------}+-- | /O(n)/. Show the tree that implements the set. The tree is shown+-- in a compressed, hanging format.+showTree :: (US a, Show a) => USet a -> String+showTree s+ = showTreeWith True False s+++{- | /O(n)/. The expression (@showTreeWith hang wide map@) shows+ the tree that implements the set. If @hang@ is+ @True@, a /hanging/ tree is shown otherwise a rotated tree is shown. If+ @wide@ is 'True', an extra wide version is shown.++> Set> putStrLn $ showTreeWith True False $ fromDistinctAscList [1..5]+> 4+> +--2+> | +--1+> | +--3+> +--5+> +> Set> putStrLn $ showTreeWith True True $ fromDistinctAscList [1..5]+> 4+> |+> +--2+> | |+> | +--1+> | |+> | +--3+> |+> +--5+> +> Set> putStrLn $ showTreeWith False True $ fromDistinctAscList [1..5]+> +--5+> |+> 4+> |+> | +--3+> | |+> +--2+> |+> +--1++-}+showTreeWith :: (US a, Show a) => Bool -> Bool -> USet a -> String+showTreeWith hang wide t+ | hang = (showsTreeHang wide [] t) ""+ | otherwise = (showsTree wide [] [] t) ""++showsTree :: (US a, Show a) => Bool -> [String] -> [String] -> USet a -> ShowS+showsTree wide lbars rbars t+ = case view t of+ Tip -> showsBars lbars . showString "|\n"+ Bin _ x (view -> Tip) (view -> Tip)+ -> showsBars lbars . shows x . showString "\n" + Bin _ x l r+ -> showsTree wide (withBar rbars) (withEmpty rbars) r .+ showWide wide rbars .+ showsBars lbars . shows x . showString "\n" .+ showWide wide lbars .+ showsTree wide (withEmpty lbars) (withBar lbars) l++showsTreeHang :: (US a, Show a) => Bool -> [String] -> USet a -> ShowS+showsTreeHang wide bars t+ = case view t of+ Tip -> showsBars bars . showString "|\n" + Bin _ x (view -> Tip) (view -> Tip) + -> showsBars bars . shows x . showString "\n" + Bin _ x l r+ -> showsBars bars . shows x . showString "\n" . + showWide wide bars .+ showsTreeHang wide (withBar bars) l .+ showWide wide bars .+ showsTreeHang wide (withEmpty bars) r++showWide :: Bool -> [String] -> String -> String+showWide wide bars + | wide = showString (concat (reverse bars)) . showString "|\n" + | otherwise = id++showsBars :: [String] -> ShowS+showsBars bars+ = case bars of+ [] -> id+ _ -> showString (concat (reverse (tail bars))) . showString node++node :: String+node = "+--"++withBar, withEmpty :: [String] -> [String]+withBar bars = "| ":bars+withEmpty bars = " ":bars++{--------------------------------------------------------------------+ Assertions+--------------------------------------------------------------------}+-- | /O(n)/. Test if the internal set structure is valid.+valid :: (US a, Ord a) => USet a -> Bool+valid t+ = balanced t && ordered t && validsize t++ordered :: (US a, Ord a) => USet a -> Bool+ordered t+ = bounded (const True) (const True) t+ where+ bounded lo hi t'+ = case view t' of+ Tip -> True+ Bin _ x l r -> (lo x) && (hi x) && bounded lo (<x) l && bounded (>x) hi r++balanced :: US a => USet a -> Bool+balanced t+ = case view t of+ Tip -> True+ Bin _ _ l r -> (size l + size r <= 1 || (size l <= delta*size r && size r <= delta*size l)) &&+ balanced l && balanced r++validsize :: US a => USet a -> Bool+validsize t+ = (realsize t == Just (size t))+ where+ realsize t'+ = case view t' of+ Tip -> Just 0+ Bin sz _ l r -> case (realsize l,realsize r) of+ (Just n,Just m) | n+m+1 == sz -> Just sz+ _ -> Nothing++{-+{--------------------------------------------------------------------+ Testing+--------------------------------------------------------------------}+testTree :: [Int] -> USet Int+testTree xs = fromList xs+test1 = testTree [1..20]+test2 = testTree [30,29..10]+test3 = testTree [1,4,6,89,2323,53,43,234,5,79,12,9,24,9,8,423,8,42,4,8,9,3]++{--------------------------------------------------------------------+ QuickCheck+--------------------------------------------------------------------}++{-+qcheck prop+ = check config prop+ where+ config = Config+ { configMaxTest = 500+ , configMaxFail = 5000+ , configSize = \n -> (div n 2 + 3)+ , configEvery = \n args -> let s = show n in s ++ [ '\b' | _ <- s ]+ }+-}+++{--------------------------------------------------------------------+ Arbitrary, reasonably balanced trees+--------------------------------------------------------------------}+instance (US a, Enum a) => Arbitrary (USet a) where+ arbitrary = sized (arbtree 0 maxkey)+ where maxkey = 10000++arbtree :: (US a, Enum a) => Int -> Int -> Int -> Gen (USet a)+arbtree lo hi n+ | n <= 0 = return tip+ | lo >= hi = return tip+ | otherwise = do{ i <- choose (lo,hi)+ ; m <- choose (1,30)+ ; let (ml,mr) | m==(1::Int)= (1,2)+ | m==2 = (2,1)+ | m==3 = (1,1)+ | otherwise = (2,2)+ ; l <- arbtree lo (i-1) (n `div` ml)+ ; r <- arbtree (i+1) hi (n `div` mr)+ ; return (bin_ (toEnum i) l r)+ } +++{--------------------------------------------------------------------+ Valid tree's+--------------------------------------------------------------------}+forValid :: (US a, Enum a,Show a,Testable b) => (USet a -> b) -> Property+forValid f+ = forAll arbitrary $ \t -> +-- classify (balanced t) "balanced" $+ classify (size t == 0) "empty" $+ classify (size t > 0 && size t <= 10) "small" $+ classify (size t > 10 && size t <= 64) "medium" $+ classify (size t > 64) "large" $+ balanced t ==> f t++forValidIntTree :: Testable a => (USet Int -> a) -> Property+forValidIntTree f+ = forValid f++forValidUnitTree :: Testable a => (USet Int -> a) -> Property+forValidUnitTree f+ = forValid f+++prop_Valid + = forValidUnitTree $ \t -> valid t++{--------------------------------------------------------------------+ Single, Insert, Delete+--------------------------------------------------------------------}+prop_Single :: Int -> Bool+prop_Single x+ = (insert x empty == singleton x)++prop_InsertValid :: Int -> Property+prop_InsertValid k+ = forValidUnitTree $ \t -> valid (insert k t)++prop_InsertDelete :: Int -> USet Int -> Property+prop_InsertDelete k t+ = not (member k t) ==> delete k (insert k t) == t++prop_DeleteValid :: Int -> Property+prop_DeleteValid k+ = forValidUnitTree $ \t -> + valid (delete k (insert k t))++{--------------------------------------------------------------------+ Balance+--------------------------------------------------------------------}+prop_Join :: Int -> Property +prop_Join x+ = forValidUnitTree $ \t ->+ let (l,r) = split x t+ in valid (join x l r)++prop_Merge :: Int -> Property +prop_Merge x+ = forValidUnitTree $ \t ->+ let (l,r) = split x t+ in valid (merge l r)+++{--------------------------------------------------------------------+ Union+--------------------------------------------------------------------}+prop_UnionValid :: Property+prop_UnionValid+ = forValidUnitTree $ \t1 ->+ forValidUnitTree $ \t2 ->+ valid (union t1 t2)++prop_UnionInsert :: Int -> USet Int -> Bool+prop_UnionInsert x t+ = union t (singleton x) == insert x t++prop_UnionAssoc :: USet Int -> USet Int -> USet Int -> Bool+prop_UnionAssoc t1 t2 t3+ = union t1 (union t2 t3) == union (union t1 t2) t3++prop_UnionComm :: USet Int -> USet Int -> Bool+prop_UnionComm t1 t2+ = (union t1 t2 == union t2 t1)+++prop_DiffValid+ = forValidUnitTree $ \t1 ->+ forValidUnitTree $ \t2 ->+ valid (difference t1 t2)++prop_Diff :: [Int] -> [Int] -> Bool+prop_Diff xs ys+ = toAscList (difference (fromList xs) (fromList ys))+ == List.sort ((List.\\) (nub xs) (nub ys))++prop_IntValid+ = forValidUnitTree $ \t1 ->+ forValidUnitTree $ \t2 ->+ valid (intersection t1 t2)++prop_Int :: [Int] -> [Int] -> Bool+prop_Int xs ys+ = toAscList (intersection (fromList xs) (fromList ys))+ == List.sort (nub ((List.intersect) (xs) (ys)))++{--------------------------------------------------------------------+ Lists+--------------------------------------------------------------------}+prop_Ordered+ = forAll (choose (5,100)) $ \n ->+ let xs = [0..n::Int]+ in fromAscList xs == fromList xs++prop_List :: [Int] -> Bool+prop_List xs+ = (sort (nub xs) == toList (fromList xs))+-}+++newtype Boxed a = Boxed a+instance US (Boxed a) where+ data USet (Boxed a) = BoxedTip | BoxedBin {-# UNPACK #-} !Size (Boxed a) !(USet (Boxed a)) !(USet (Boxed a))+ view BoxedTip = Tip+ view (BoxedBin s i l r) = Bin s i l r+ tip = BoxedTip+ bin = BoxedBin++instance US Char where+ data USet Char = CharTip | CharBin {-# UNPACK #-} !Size {-# UNPACK #-} !Char !(USet Char) !(USet Char)+ view CharTip = Tip+ view (CharBin s i l r) = Bin s i l r+ tip = CharTip+ bin = CharBin+instance US Int where+ data USet Int = IntTip | IntBin {-# UNPACK #-} !Size {-# UNPACK #-} !Int !(USet Int) !(USet Int)+ view IntTip = Tip+ view (IntBin s i l r) = Bin s i l r+ tip = IntTip+ bin = IntBin++instance US Integer where+ data USet Integer = IntegerTip | IntegerBin {-# UNPACK #-} !Size {-# UNPACK #-} !Integer !(USet Integer) !(USet Integer)+ view IntegerTip = Tip+ view (IntegerBin s i l r) = Bin s i l r+ tip = IntegerTip+ bin = IntegerBin++instance US Int8 where+ data USet Int8 = Int8Tip | Int8Bin {-# UNPACK #-} !Size {-# UNPACK #-} !Int8 !(USet Int8) !(USet Int8)+ view Int8Tip = Tip+ view (Int8Bin s i l r) = Bin s i l r+ tip = Int8Tip+ bin = Int8Bin++instance US Int16 where+ data USet Int16 = Int16Tip | Int16Bin {-# UNPACK #-} !Size {-# UNPACK #-} !Int16 !(USet Int16) !(USet Int16)+ view Int16Tip = Tip+ view (Int16Bin s i l r) = Bin s i l r+ tip = Int16Tip+ bin = Int16Bin++instance US Int32 where+ data USet Int32 = Int32Tip | Int32Bin {-# UNPACK #-} !Size {-# UNPACK #-} !Int32 !(USet Int32) !(USet Int32)+ view Int32Tip = Tip+ view (Int32Bin s i l r) = Bin s i l r+ tip = Int32Tip+ bin = Int32Bin++instance US Int64 where+ data USet Int64 = Int64Tip | Int64Bin {-# UNPACK #-} !Size {-# UNPACK #-} !Int64 !(USet Int64) !(USet Int64)+ view Int64Tip = Tip+ view (Int64Bin s i l r) = Bin s i l r+ tip = Int64Tip+ bin = Int64Bin++instance US Word8 where+ data USet Word8 = Word8Tip | Word8Bin {-# UNPACK #-} !Size {-# UNPACK #-} !Word8 !(USet Word8) !(USet Word8)+ view Word8Tip = Tip+ view (Word8Bin s i l r) = Bin s i l r+ tip = Word8Tip+ bin = Word8Bin++instance US Word16 where+ data USet Word16 = Word16Tip | Word16Bin {-# UNPACK #-} !Size {-# UNPACK #-} !Word16 !(USet Word16) !(USet Word16)+ view Word16Tip = Tip+ view (Word16Bin s i l r) = Bin s i l r+ tip = Word16Tip+ bin = Word16Bin++instance US Word32 where+ data USet Word32 = Word32Tip | Word32Bin {-# UNPACK #-} !Size {-# UNPACK #-} !Word32 !(USet Word32) !(USet Word32)+ view Word32Tip = Tip+ view (Word32Bin s i l r) = Bin s i l r+ tip = Word32Tip+ bin = Word32Bin++instance US Word64 where+ data USet Word64 = Word64Tip | Word64Bin {-# UNPACK #-} !Size {-# UNPACK #-} !Word64 !(USet Word64) !(USet Word64)+ view Word64Tip = Tip+ view (Word64Bin s i l r) = Bin s i l r+ tip = Word64Tip+ bin = Word64Bin++instance US Double where+ data USet Double = DoubleTip | DoubleBin {-# UNPACK #-} !Size {-# UNPACK #-} !Double !(USet Double) !(USet Double)+ view DoubleTip = Tip+ view (DoubleBin s i l r) = Bin s i l r+ tip = DoubleTip+ bin = DoubleBin++instance US Float where+ data USet Float = FloatTip | FloatBin {-# UNPACK #-} !Size {-# UNPACK #-} !Float !(USet Float) !(USet Float)+ view FloatTip = Tip+ view (FloatBin s i l r) = Bin s i l r+ tip = FloatTip+ bin = FloatBin+
monoids.cabal view
@@ -1,5 +1,5 @@ name: monoids-version: 0.1.32+version: 0.1.33 license: BSD3 license-file: LICENSE author: Edward A. Kmett@@ -70,11 +70,13 @@ Data.Ring.Module.AutomaticDifferentiation Data.Ring.Semi Data.Ring.Semi.BitSet+ Data.Ring.Semi.Kleene Data.Ring.Semi.Near Data.Ring.Semi.Near.Trie Data.Ring.Semi.Natural Data.Ring.Semi.Ord Data.Ring.Semi.Tropical Data.Ring.Sugar+ Data.Set.Unboxed ghc-options: -Wall -fno-warn-duplicate-exports