packages feed

word8set (empty) → 0.1

raw patch · 4 files changed

+824/−0 lines, 4 filesdep +QuickCheckdep +basedep +deepseq

Dependencies added: QuickCheck, base, deepseq, lattices, template-haskell, wide-word

Files

+ CHANGELOG.md view
@@ -0,0 +1,3 @@+## 0.1++* First version. Released on an unsuspecting world.
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2023, Oleg Grenrus++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * Neither the name of Oleg Grenrus nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ src/Data/Word8Set.hs view
@@ -0,0 +1,745 @@+{-# LANGUAGE BangPatterns          #-}+{-# LANGUAGE CPP                   #-}+{-# LANGUAGE TemplateHaskellQuotes #-}+{-# LANGUAGE Trustworthy           #-}+{-# LANGUAGE TypeFamilies          #-}+-- | The 'Word8Set' type represents a set of elements of type 'Word8'.+--+-- The interface of this module mimics the "Data.Set" and/or "Data.IntSet"+-- module interfaces from @containers package.+--+-- These module is intended to be imported qualified, to avoid name clashes with Prelude functions, e.g.+--+-- @+-- import Data.Word8Set (Word8Set)+-- import qualified Data.Word8Set as W8S+-- @+--+-- == Implementation+-- The implementation is based on 'Word256' type. 'Word8Set' is 256 bits.+--+module Data.Word8Set (+    -- * Set type+    Word8Set,+    Key,++    -- * Construction+    empty,+    full,+    singleton,+    range,++    -- * Insertion+    insert,++    -- * Deletion+    delete,++    -- * Generalized insertion/deletion+    alterF,++    -- * Query+    member,+    notMember,+    lookupLT,+    lookupGT,+    lookupLE,+    lookupGE,+    null,+    isFull,+    isSingleton,+    isRange,+    size,+    isSubsetOf,+    isProperSubsetOf,+    disjoint,++    -- * Combine+    union,+    unions,+    difference,+    (\\),+    intersection,+    complement,++    -- * Filter+    filter,+    partition,++    -- * Map+    map,++    -- * Folds+    foldr,+    foldl,++    -- ** Strict folds+    foldr',+    foldl',++    -- * Min\/Max+    findMin,+    findMax,+    deleteMin,+    deleteMax,+    maxView,+    minView,++    -- * Conversion+    -- ** to/fromList+    elems,+    toList,+    fromList,+    fromFoldable,++    -- ** to/from Word256+    toWord256,+    fromWord256,++    -- ** to/from ASCII Strings+    toASCII,+    fromASCII,+) where++import Prelude+       (Bool (..), Eq ((==)), Functor (fmap), Int, Maybe (..), Ord, Show (showsPrec), String, fromIntegral, fst, maybe, negate, not,+       otherwise, return, showParen, showString, snd, ($), (&&), (+), (-), (.), (/=), (<=), (>))++import Algebra.Lattice       (BoundedJoinSemiLattice (..), BoundedMeetSemiLattice (..), Lattice (..))+import Control.DeepSeq       (NFData (..))+import Data.Bits             ((.&.), (.|.))+import Data.Char             (chr, ord)+import Data.Monoid           (Monoid (..))+import Data.Semigroup        (Semigroup (..))+import Data.WideWord.Word256 (Word256 (..))+import Data.Word             (Word8)+import Test.QuickCheck       (Arbitrary (..), CoArbitrary (..), Function (..), functionMap)++import Language.Haskell.TH.Syntax (Lift (..))++import qualified Data.Bits     as Bits+import qualified Data.Foldable as F+import qualified GHC.Exts++-- $setup+-- >>> import Prelude (even, (+), flip)++-------------------------------------------------------------------------------+-- Types+-------------------------------------------------------------------------------++-- | A set of 'Word8' numbers.+--+-- Implemented using 'Word256'.+newtype Word8Set = W8S Word256+  deriving (Eq, Ord)++-- | Key of 'Word8Set' is 'Word8'.+type Key = Word8++-------------------------------------------------------------------------------+-- Instances+-------------------------------------------------------------------------------++instance Show Word8Set where+    showsPrec d xs = showParen (d > 10) $ showString "fromList " . showsPrec 11 (toList xs)++instance NFData Word8Set where+    rnf (W8S xs) = rnf xs++instance Lift Word8Set where+    lift (W8S (Word256 a b c d)) =+        [| W8S (Word256 a b c d) |]++#if MIN_VERSION_template_haskell(2,16,0)+    liftTyped (W8S (Word256 a b c d)) =+        [|| W8S (Word256 a b c d) ||]+#endif++instance Semigroup Word8Set where+    (<>) = union++instance Monoid Word8Set where+    mempty = empty+    mappend = (<>)++instance Arbitrary Word8Set where+    arbitrary = do+        a <- arbitrary+        b <- arbitrary+        c <- arbitrary+        d <- arbitrary+        return (W8S (Word256 a b c d))++    shrink xs = fmap fromList (shrink (toList xs)) where++instance CoArbitrary Word8Set where+    coarbitrary (W8S (Word256 a b c d)) = coarbitrary (a,b,c,d)++instance Function Word8Set where+    function = functionMap from to where+        from (W8S (Word256 a b c d)) = (a, b, c, d)+        to (a,b,c,d) = W8S (Word256 a b c d)++instance Lattice Word8Set where+    (\/) = union+    (/\) = intersection++instance BoundedJoinSemiLattice Word8Set where+    bottom = empty++instance BoundedMeetSemiLattice Word8Set where+    top = full++instance GHC.Exts.IsList Word8Set where+  type Item Word8Set = Key+  fromList = fromList+  toList   = toList++-------------------------------------------------------------------------------+-- Construction+-------------------------------------------------------------------------------++-- | The empty set.+--+-- >>> empty+-- fromList []+--+empty :: Word8Set+empty = W8S Bits.zeroBits++-- | The full set.+--+-- >>> full+-- fromList [0,1,2,3,4,5,6,7,8,9,10,11,12,...,255]+--+full :: Word8Set+full = W8S ones++ones :: Word256+ones = Bits.complement Bits.zeroBits++-- | A set of one element.+--+-- >>> singleton 127+-- fromList [127]+--+singleton :: Key -> Word8Set+singleton x = W8S (Bits.bit (fromIntegral x))++-- | A set of inclusive range.+--+-- >>> range 10 20+-- fromList [10,11,12,13,14,15,16,17,18,19,20]+--+range :: Key -> Key -> Word8Set+range mi ma+    | mi <= ma  = W8S $ Bits.shiftL (Bits.shiftR ones (fromIntegral (negate (1 + ma - mi)))) (fromIntegral mi)+    | otherwise = empty++-------------------------------------------------------------------------------+-- Insertion+-------------------------------------------------------------------------------++-- | Add a value to the set.+--+-- >>> insert 10 (range 15 20)+-- fromList [10,15,16,17,18,19,20]+--+-- >>> insert 10 (range 10 15)+-- fromList [10,11,12,13,14,15]+--+insert :: Key -> Word8Set -> Word8Set+insert x (W8S xs) = W8S (Bits.setBit xs (fromIntegral x))++-------------------------------------------------------------------------------+-- Deletion+-------------------------------------------------------------------------------++-- | Delete a value in the set. Returns the original set when the value was not present.+--+-- >>> delete 10 (range 5 15)+-- fromList [5,6,7,8,9,11,12,13,14,15]+--+-- >>> delete 10 (range 1 10)+-- fromList [1,2,3,4,5,6,7,8,9]+--+delete :: Key -> Word8Set -> Word8Set+delete x (W8S xs) = W8S (Bits.clearBit xs (fromIntegral x))++-------------------------------------------------------------------------------+-- Generalized insertion/deletion+-------------------------------------------------------------------------------++-- | Generalized insetion deletion.+alterF :: Functor f => (Bool -> f Bool) -> Key -> Word8Set -> f Word8Set+alterF f x xs+    | member x xs = fmap (\b -> if b then xs else delete x xs) (f True)+    | otherwise   = fmap (\b -> if b then insert x xs else xs) (f False)++-------------------------------------------------------------------------------+-- Query+-------------------------------------------------------------------------------++-- | Is the set empty?+--+-- >>> null empty+-- True+--+-- >>> null (range 10 20)+-- False+--+null :: Word8Set -> Bool+null (W8S xs) = xs == Bits.zeroBits++-- | Is the set full?+--+-- >>> isFull full+-- True+--+-- >>> isFull (range 1 255)+-- False+--+isFull :: Word8Set -> Bool+isFull (W8S xs) = xs == ones++-- | Cardinality of the set.+--+-- >>> size empty+-- 0+--+-- >>> size (union (range 10 20) (range 30 40))+-- 22+--+size :: Word8Set -> Int+size (W8S xs) = Bits.popCount xs++-- | Is the value a member of the set?+--+-- >>> member 5 (range 10 20)+-- False+--+-- >>> member 15 (range 10 20)+-- True+--+member :: Key -> Word8Set -> Bool+member x (W8S xs) = Bits.testBit xs (fromIntegral x)++-- | Is the element not in the set?+--+-- >>> notMember 5 (range 10 20)+-- True+--+-- >>> notMember 15 (range 10 20)+-- False+--+notMember :: Key -> Word8Set -> Bool+notMember x xs = not (member x xs)++-- | Is this a subset? @(s1 `isSubsetOf` s2)@ tells whether s1 is a subset of s2.+--+-- >>> isSubsetOf (range 10 20) (range 5 25)+-- True+--+-- >>> isSubsetOf (range 10 20) (range 10 20)+-- True+--+-- >>> isSubsetOf (range 5 25) (range 10 20)+-- False+--+isSubsetOf :: Word8Set -> Word8Set -> Bool+isSubsetOf a b = b == union a b++-- | Is this a proper subset? Is this a proper subset? (ie. a subset but not equal).+--+-- >>> isProperSubsetOf (range 10 20) (range 5 25)+-- True+--+-- >>> isProperSubsetOf (range 10 20) (range 10 20)+-- False+--+-- >>> isProperSubsetOf (range 5 25) (range 10 20)+-- False+--+isProperSubsetOf :: Word8Set -> Word8Set -> Bool+isProperSubsetOf a b = b == union a b && a /= b++-- | Is set singleton?+--+-- >>> isSingleton empty+-- Nothing+--+-- >>> isSingleton full+-- Nothing+--+-- >>> isSingleton (singleton 5)+-- Just 5+--+-- >>> isSingleton (fromList [3, 5])+-- Nothing+--+isSingleton :: Word8Set -> Maybe Key+isSingleton (W8S ws)+    | Bits.popCount ws /= 1 = Nothing+    | otherwise             = Just (fromIntegral (ctz ws))++-- | Is set of the form @'range' l r@?+--+-- >>> isRange empty+-- Nothing+--+-- >>> isRange full+-- Just (0,255)+--+-- >>> isRange (singleton 5)+-- Just (5,5)+--+-- >>> isRange (range 10 20)+-- Just (10,20)+--+-- >>> isRange (fromList [3, 5])+-- Nothing+--+isRange :: Word8Set -> Maybe (Key, Key)+isRange (W8S 0)  = Nothing+isRange (W8S ws) = if Bits.popCount ws + l + r == 256 then Just (fromIntegral l, fromIntegral (255 - r)) else Nothing+  where+    r = clz ws+    l = ctz ws++-- | Check whether two sets are disjoint (i.e. their intersection is empty).+--+-- >>> disjoint (range 11 20) (range 21 30)+-- True+--+disjoint :: Word8Set -> Word8Set -> Bool+disjoint xs ys = intersection xs ys == empty++-- | Find largest element smaller than the given one.+--+-- >>> lookupLT 3 (fromList [3, 5])+-- Nothing+-- >>> lookupLT 5 (fromList [3, 5])+-- Just 3+--+-- >>> lookupLT 0 full+-- Nothing+lookupLT :: Key -> Word8Set -> Maybe Key+lookupLT 0 _  = Nothing+lookupLT x xs = lookupLE (x - 1) xs++-- | Find smallest element greater than the given one.+--+-- >>> lookupGT 4 (fromList [3, 5])+-- Just 5+--+-- >>> lookupGT 5 (fromList [3, 5])+-- Nothing+--+-- >>> lookupGT 255 full+-- Nothing+--+lookupGT :: Key -> Word8Set -> Maybe Key+lookupGT 255 _  = Nothing+lookupGT x   xs = lookupGE (x + 1) xs++-- | Find largest element smaller or equal to the given one.+--+-- >>> lookupLE 2 (fromList [3, 5])+-- Nothing+--+-- >>> lookupLE 4 (fromList [3, 5])+-- Just 3+--+-- >>> lookupLE 5 (fromList [3, 5])+-- Just 5+--+lookupLE :: Key -> Word8Set -> Maybe Key+lookupLE x xs = fmap fst (maxView (intersection xs (range 0 x)))++-- | Find smallest element greater or equal to the given one.+--+-- >>> lookupGE 3 (fromList [3, 5])+-- Just 3+--+-- >>> lookupGE 4 (fromList [3, 5])+-- Just 5+--+-- >>> lookupGE 6 (fromList [3, 5])+-- Nothing+--+lookupGE :: Key -> Word8Set -> Maybe Key+lookupGE x xs = fmap fst (minView (intersection xs (range x 255)))++-------------------------------------------------------------------------------+-- Combine+-------------------------------------------------------------------------------++-- | The complement of the set.+complement :: Word8Set -> Word8Set+complement (W8S xs) = W8S (Bits.complement xs)++-- | The union of two sets.+union :: Word8Set -> Word8Set -> Word8Set+union (W8S xs) (W8S ys) = W8S (xs .|. ys)++-- | The union of a list of sets.+unions :: F.Foldable f => f Word8Set -> Word8Set+unions xs = F.foldl' union empty xs++-- | The intersection between two sets.+intersection :: Word8Set -> Word8Set -> Word8Set+intersection (W8S xs) (W8S ys) = W8S (xs .&. ys)++-- | Difference between two sets.+difference :: Word8Set -> Word8Set -> Word8Set+difference xs ys = intersection xs (complement ys)++-- | See 'difference'.+(\\) :: Word8Set -> Word8Set -> Word8Set+m1 \\ m2 = difference m1 m2++-------------------------------------------------------------------------------+-- Filter+-------------------------------------------------------------------------------++-- | Filter all elements that satisfy some predicate.+--+-- >>> filter even (range 10 20)+-- fromList [10,12,14,16,18,20]+--+filter :: (Key -> Bool) -> Word8Set -> Word8Set+filter p = foldl' (\acc x -> if p x then insert x acc else acc) empty++-- | Partition the set according to some predicate.+--+-- >>> partition even (range 10 20)+-- (fromList [10,12,14,16,18,20],fromList [11,13,15,17,19])+--+partition :: (Key -> Bool) -> Word8Set -> (Word8Set,Word8Set)+partition p = foldl' (\(l, r) x -> if p x then (insert x l, r) else (l, insert x r)) (empty, empty)++-------------------------------------------------------------------------------+-- Map+-------------------------------------------------------------------------------++-- |  @'map' f s@ is the set obtained by applying @f@ to each element of @s@.+--+-- >>> map (+ 1) (fromList [0, 10, 250, 255])+-- fromList [0,1,11,251]+--+map :: (Key -> Key) -> Word8Set -> Word8Set+map f = foldl' (\acc k -> insert (f k) acc) empty++-------------------------------------------------------------------------------+-- Folds+-------------------------------------------------------------------------------++-- | Lazy right fold.+--+-- >>> foldr (:) [] (unions [range 10 20, range 70 73, range 130 132, range 200 202, singleton 255])+-- [10,11,12,13,14,15,16,17,18,19,20,70,71,72,73,130,131,132,200,201,202,255]+--+foldr :: (Key -> b -> b) -> b -> Word8Set -> b+foldr f z0 (W8S (Word256 a0 b0 c0 d0)) = go0 a0 b0 c0 d0 z0 where+    go0 0 !b !c !d acc = go1 b c d acc+    go0 a  b  c  d acc = let !x = clz a in go0 (Bits.clearBit a (63 - x)) b c d (f (255 - fromIntegral x) acc)++    go1 0 !c d acc = go2 c d acc+    go1 b  c d acc = let !x = clz b in go1 (Bits.clearBit b (63 - x)) c d (f (191 - fromIntegral x) acc)++    go2 0 !d acc = go3 d acc+    go2 c  d acc = let !x = clz c in go2 (Bits.clearBit c (63 - x)) d (f (127 - fromIntegral x) acc)++    go3 0 acc = acc+    go3 a acc = let !x = clz a in go3 (Bits.clearBit a (63 - x)) (f (63 - fromIntegral x) acc)++-- | Strict right fold.+--+foldr' :: (Key -> b -> b) -> b -> Word8Set -> b+foldr' f z0 (W8S (Word256 a0 b0 c0 d0)) = go0 a0 b0 c0 d0 z0 where+    go0 0 !b !c !d !acc = go1 b c d acc+    go0 a  b  c  d  acc = let !x = clz a in go0 (Bits.clearBit a (63 - x)) b c d (f (255 - fromIntegral x) acc)++    go1 0 !c d !acc = go2 c d acc+    go1 b  c d  acc = let !x = clz b in go1 (Bits.clearBit b (63 - x)) c d (f (191 - fromIntegral x) acc)++    go2 0 !d !acc = go3 d acc+    go2 c  d  acc = let !x = clz c in go2 (Bits.clearBit c (63 - x)) d (f (127 - fromIntegral x) acc)++    go3 0 !acc = acc+    go3 a  acc = let !x = clz a in go3 (Bits.clearBit a (63 - x)) (f (63 - fromIntegral x) acc)++-- | Lazy left fold.+--+-- >>> foldl (flip (:)) [] (unions [range 10 20, range 70 73, range 130 132, range 200 202, singleton 255])+-- [255,202,201,200,132,131,130,73,72,71,70,20,19,18,17,16,15,14,13,12,11,10]+--+foldl :: (a -> Key -> a) -> a -> Word8Set -> a+foldl f z0 (W8S (Word256 a0 b0 c0 d0)) = go0 a0 b0 c0 d0 z0 where+    go0 !a !b !c 0 acc = go1 a b c acc+    go0  a  b  c d acc = let !x = ctz d in go0 a b c (Bits.clearBit d x) (f acc (fromIntegral x))++    go1 !a !b 0 acc = go2 a b acc+    go1  a  b c acc = let !x = ctz c in go1 a b (Bits.clearBit c x) (f acc (fromIntegral x + 64))++    go2 !a 0 acc = go3 a acc+    go2  a b acc = let !x = ctz b in go2 a (Bits.clearBit b x) (f acc (fromIntegral x + 128))++    go3 0 acc = acc+    go3 a acc = let !x = ctz a in go3 (Bits.clearBit a x) (f acc (fromIntegral x + 192))++-- | Strict left fold.+--+foldl' :: (a -> Key -> a) -> a -> Word8Set -> a+foldl' f z0 (W8S (Word256 a0 b0 c0 d0)) = go0 a0 b0 c0 d0 z0 where+    go0 !a !b !c 0 !acc = go1 a b c acc+    go0  a  b  c d  acc = let !x = ctz d in go0 a b c (Bits.clearBit d x) (f acc (fromIntegral x))++    go1 !a !b 0 !acc = go2 a b acc+    go1  a  b c  acc = let !x = ctz c in go1 a b (Bits.clearBit c x) (f acc (fromIntegral x + 64))++    go2 !a 0 !acc = go3 a acc+    go2  a b  acc = let !x = ctz b in go2 a (Bits.clearBit b x) (f acc (fromIntegral x + 128))++    go3 0 !acc = acc+    go3 a  acc = let !x = ctz a in go3 (Bits.clearBit a x) (f acc (fromIntegral x + 192))++-------------------------------------------------------------------------------+-- Min/Max+-------------------------------------------------------------------------------++-- | The minimal element of the set.+--+-- >>> findMin (fromList [3, 5])+-- 3+--+-- Returns 0 for empty set.+--+-- >>> findMin empty+-- 0+--+findMin :: Word8Set -> Word8+findMin (W8S xs) = fromIntegral (ctz xs)++-- | The maximal element of the set.+--+-- >>> findMax (fromList [3, 5])+-- 5+--+-- Returns 255 for empty set.+--+-- >>> findMax empty+-- 255+--+findMax :: Word8Set -> Word8+findMax (W8S xs) = fromIntegral (255 - clz xs)++-- | Delete the minimal element. Returns an empty set if the set is empty.+deleteMin :: Word8Set -> Word8Set+deleteMin = maybe empty snd . minView++-- | Delete the maximal element. Returns an empty set if the set is empty.+deleteMax :: Word8Set -> Word8Set+deleteMax = maybe empty snd . minView++-- | Retrieves the maximal key of the set, and the set+-- stripped of that element, or 'Nothing' if passed an empty set.+--+-- >>> maxView (fromList [3, 5])+-- Just (5,fromList [3])+--+-- >>> maxView empty+-- Nothing+--+maxView :: Word8Set -> Maybe (Key, Word8Set)+maxView xs+    | null xs   = Nothing+    | otherwise = let !x = findMax xs in Just (x, delete x xs)++-- | Retrieves the minimal key of the set, and the set+-- stripped of that element, or 'Nothing' if passed an empty set.+--+-- >>> minView (fromList [3, 5])+-- Just (3,fromList [5])+--+-- >>> minView empty+-- Nothing+--+minView :: Word8Set -> Maybe (Key, Word8Set)+minView xs+    | null xs   = Nothing+    | otherwise = let !x = findMin xs in Just (x, delete x xs)++-------------------------------------------------------------------------------+-- List+-------------------------------------------------------------------------------++-- | The elements of a set in ascending order.+elems :: Word8Set -> [Key]+elems = toList++-- | The elements of a set in ascending order.+toList :: Word8Set -> [Key]+toList xs = GHC.Exts.build (\c n -> foldr c n xs)++-- | Create a set from a list of 'Word8's.+fromList :: [Key] -> Word8Set+fromList w8s = F.foldl' (\acc x -> insert x acc) empty w8s++-- | Create a set from a foldable of 'Word8's.+fromFoldable :: F.Foldable f => f Key -> Word8Set+#if MIN_VERSION_base(4,13,0)+fromFoldable = F.foldMap' singleton+#else+fromFoldable = F.foldl' (\acc x -> insert x acc) empty+#endif++-------------------------------------------------------------------------------+-- Word256+-------------------------------------------------------------------------------++-- | Convert set to 'Word256'.+toWord256 :: Word8Set -> Word256+toWord256 (W8S xs) = xs++-- | Create set from 'Word256'.+fromWord256 :: Word256 -> Word8Set+fromWord256 = W8S++-------------------------------------------------------------------------------+-- ASCII+-------------------------------------------------------------------------------++-- | Create ASCII string from a set.+--+-- >>> toASCII (range 100 120)+-- "defghijklmnopqrstuvwx"+--+toASCII :: Word8Set -> String+toASCII = fmap (chr . fromIntegral) . toList++-- | Create set from ASCII string.+--+-- >>> fromASCII "foobar"+-- fromList [97,98,102,111,114]+--+-- Non-ASCII codepoints are truncated:+--+-- >>> fromASCII "\1000"+-- fromList [232]+--+fromASCII :: String -> Word8Set+fromASCII = fromList .  fmap (fromIntegral . ord)++-------------------------------------------------------------------------------+-- Helpers+-------------------------------------------------------------------------------++clz :: Bits.FiniteBits a => a -> Int+clz = Bits.countLeadingZeros+{-# INLINE clz #-}++ctz :: Bits.FiniteBits a => a -> Int+ctz = Bits.countTrailingZeros+{-# INLINE ctz #-}
+ word8set.cabal view
@@ -0,0 +1,46 @@+cabal-version:      3.0+name:               word8set+version:            0.1+synopsis:           Word8 set+description:        Set of Word8 numbers. Backed up by Word256.+category:           Data+author:             Oleg Grenrus <oleg.grenrus@iki.fi>+maintainer:         Oleg Grenrus <oleg.grenrus@iki.fi>+homepage:           https://github.com/phadej/word8set+bug-reports:        https://github.com/phadej/word8set/issues+license:            BSD-3-Clause+license-file:       LICENSE+build-type:         Simple+extra-source-files: CHANGELOG.md+tested-with:+  GHC ==8.0.2+   || ==8.2.2+   || ==8.4.4+   || ==8.6.5+   || ==8.8.4+   || ==8.10.7+   || ==9.0.2+   || ==9.2.7+   || ==9.4.5+   || ==9.6.1++source-repository head+  type:     git+  location: https://github.com/phadej/word8set.git++library+  default-language: Haskell2010+  hs-source-dirs:   src+  exposed-modules:  Data.Word8Set++  -- boot libraries+  build-depends:+    , base              >=4.9     && <4.19+    , deepseq           >=1.4.2.0 && <1.5+    , template-haskell  >=2.11    && <2.21++  -- other dependencies+  build-depends:+    , lattices    ^>=2.2+    , QuickCheck  ^>=2.14.2+    , wide-word   ^>=0.1.5.0