data-flagset (empty) → 1.0.0.0
raw patch · 4 files changed
+267/−0 lines, 4 filesdep +basesetup-changed
Dependencies added: base
Files
- Data/FlagSet.hs +173/−0
- LICENSE +20/−0
- Setup.hs +2/−0
- data-flagset.cabal +72/−0
+ Data/FlagSet.hs view
@@ -0,0 +1,173 @@+{-# LANGUAGE DeriveDataTypeable #-}+-- | +-- = Introduction+-- This module provides a data type for a set of flags. Flags are stored+-- efficiently as bits of an unsigned integer.+--+-- This module is meant to be imported qualified:+--+-- @+-- import qualified Data.FlagSet as FlagSet+-- import Data.FlagSet (FlagSet)+-- @+--+-- The API is basically the same as that of "Data.Set" from the @containers@ package.+--+-- The functions `fromList` and `member` also have aliases that can be used +-- unqualified:+-- +-- @+-- import Data.FlagSet (flags, hasFlag)+-- @+--+-- = Examples+--+-- @+-- import qualified Data.FlagSet as FlagSet+-- import Data.FlagSet (FlagSet, flags, hasFlag)+--+-- data WeekDay = Monday | Tuesday | Wednesday | Thursday | Friday | Saturday | Sunday+-- deriving (Eq, Show, Enum, Bounded)+--+-- workDays = flags [Monday .. Friday]+-- weekEndDays = flags [Saturday, Sunday]+-- allDays = FlagSet.full+--+-- worksOnTheWeekEnd :: FlagSet WeekDay -> Bool+-- worksOnTheWeekEnd = not . FlagSet.null . FlagSet.intersection weekEndDays+--+-- worksOnSunday :: FlagSet WeekDay -> Bool+-- worksOnSunday = hasFlag Sunday+--+-- workDayPay :: Rational+-- workDayPay = ...+-- weekEndDayPay :: Rational+-- weekEndDayPay = ...+--+-- pay :: FlagSet WeekDay -> Rational+-- pay daysWorking = workDayPay * countDays workDays + weekEndDayPay * countDays weekEndDays+-- where+-- countDays = fromIntegral . FlagSet.size . FlagSet.intersection daysWorking+-- @+module Data.FlagSet+ ( -- * Types+ FlagSet+ -- * Construction+ , fromList, flags, empty, singleton, full+ -- * Modification+ , insert, delete, union, unions, difference, intersection+ -- * Tests+ , member, hasFlag, null+ -- * Other+ , toList, size+ ) where++import Data.Data (Data)+import Data.Typeable (Typeable)+import Data.Word (Word32)+import Data.Bits (setBit, testBit, clearBit, (.|.), (.&.), complement, popCount)+import Data.Monoid (Monoid(..))+import Prelude hiding (null)++-- | A set of flags.+--+-- For most functions operating on flag sets, there must be an `Enum`+-- instance for @a@. Some functions also require `Bounded`.+--+-- You must ensure that `fromEnum` only returns values in the range+-- @[0 .. 31]@, otherwise an error can occur.+-- +-- In the `Monoid` instance, `mempty` is `empty` and `mappend`/`<>` is `union`.+newtype FlagSet a = MkFlagSet Word32 deriving (Data, Typeable)++instance Eq (FlagSet a) where+ MkFlagSet x == MkFlagSet y = x == y++instance Ord (FlagSet a) where+ compare (MkFlagSet x) (MkFlagSet y) = compare x y++instance (Show a, Enum a) => Show (FlagSet a) where+ showsPrec p fs = showParen (p > 10) $+ showString "fromList " . shows (toList fs)++instance Monoid (FlagSet a) where+ mempty = empty+ mappend = union++-- | Alias for `fromList` that can be imported unqualified.+flags :: Enum a => [a] -> FlagSet a+flags = fromList++-- | Alias for `member` that can be imported unqualified.+hasFlag :: Enum a => a -> FlagSet a -> Bool+hasFlag = member++-- | Create a flag set from a list of flags. Input list can contain duplicates.+fromList :: Enum a => [a] -> FlagSet a+fromList vals = go vals 0+ where+ go [] acc = MkFlagSet acc+ go (v:vs) acc = withBit "fromList" v (go vs . setBit acc)++-- | Test whether a flag set contains a value.+member :: Enum a => a -> FlagSet a -> Bool+member v (MkFlagSet bits) = withBit "member" v (testBit bits)++withBit :: Enum a => String -> a -> (Int -> b) -> b+withBit fun v cont =+ let+ n = fromEnum v+ in+ if n < 0 || n > 31+ then error $ "Data.FlagSet." ++ fun ++ ": enum out of range"+ else cont n++-- | Convert a flag set to a list of values. The values will be ordered+-- according to the order defined by `fromEnum` and there will not be any+-- duplicates.+toList :: Enum a => FlagSet a -> [a]+toList (MkFlagSet bits) = map toEnum $ filter (testBit bits) [0 .. 31]++-- | The empty flag set.+empty :: FlagSet a+empty = MkFlagSet 0++-- | A flag set containing a single value.+singleton :: Enum a => a -> FlagSet a+singleton v = withBit "singleton" v (MkFlagSet . setBit 0)++-- | The union of two flag sets.+union :: FlagSet a -> FlagSet a -> FlagSet a+union (MkFlagSet x) (MkFlagSet y) = MkFlagSet (x .|. y)++-- | The union of multiple flag sets.+unions :: [FlagSet a] -> FlagSet a+unions = foldl union empty++-- | The difference of two flag sets.+difference :: FlagSet a -> FlagSet a -> FlagSet a+difference (MkFlagSet x) (MkFlagSet y) = MkFlagSet (x .&. complement y)++-- | The intersection of two flag sets.+intersection :: FlagSet a -> FlagSet a -> FlagSet a+intersection (MkFlagSet x) (MkFlagSet y) = MkFlagSet (x .&. y)++-- | The flag set that contains every value.+full :: (Enum a, Bounded a) => FlagSet a+full = fromList [minBound .. maxBound]++-- | Insert a value into a flag set.+insert :: Enum a => a -> FlagSet a -> FlagSet a+insert v (MkFlagSet bits) = withBit "insert" v (MkFlagSet . setBit bits)++-- | Remove a value from a flag set.+delete :: Enum a => a -> FlagSet a -> FlagSet a+delete v (MkFlagSet bits) = withBit "delete" v (MkFlagSet . clearBit bits)++-- | Test whether a flag set is empty.+null :: FlagSet a -> Bool+null = (== empty)++-- | The number of values in a flag set.+size :: FlagSet a -> Int+size (MkFlagSet bits) = popCount bits
+ LICENSE view
@@ -0,0 +1,20 @@+Copyright (c) 2015 Tobias Brandt++Permission is hereby granted, free of charge, to any person obtaining+a copy of this software and associated documentation files (the+"Software"), to deal in the Software without restriction, including+without limitation the rights to use, copy, modify, merge, publish,+distribute, sublicense, and/or sell copies of the Software, and to+permit persons to whom the Software is furnished to do so, subject to+the following conditions:++The above copyright notice and this permission notice shall be included+in all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ data-flagset.cabal view
@@ -0,0 +1,72 @@+-- Initial data-flagset.cabal generated by cabal init. For further +-- documentation, see http://haskell.org/cabal/users-guide/++-- The name of the package.+name: data-flagset++-- The package version. See the Haskell package versioning policy (PVP) +-- for standards guiding when and how versions should be incremented.+-- http://www.haskell.org/haskellwiki/Package_versioning_policy+-- PVP summary: +-+------- breaking API changes+-- | | +----- non-breaking API additions+-- | | | +--- code changes with no API change+version: 1.0.0.0++-- A short (one-line) description of the package.+synopsis: An efficient data type for sets of flags++-- A longer description of the package.+description: This package provides a data type for representing a set of+ enum flags with an API similar to that of Data.Set from+ the containers package.++-- The license under which the package is released.+license: MIT++-- The file containing the license text.+license-file: LICENSE++-- The package author(s).+author: Tobias Brandt++-- An email address to which users can send suggestions, bug reports, and +-- patches.+maintainer: tob.brandt@gmail.com++-- A copyright notice.+copyright: Copyright 2015, Tobias Brandt++category: Data++build-type: Simple++-- Extra files to be distributed with the package, such as examples or a +-- README.+-- extra-source-files: ++-- Constraint on the version of Cabal needed to build this package.+cabal-version: >=1.10+++library+ -- Modules exported by the library.+ exposed-modules: Data.FlagSet+ + -- Modules included in this library but not exported.+ -- other-modules: + + -- LANGUAGE extensions used by modules in this package.+ -- other-extensions: + + -- Other library packages from which modules are imported.+ build-depends: base >=4.5 && <4.9+ + -- Directories containing source files.+ -- hs-source-dirs: + + -- Base language which the package is written in.+ default-language: Haskell2010+ +source-repository head+ type: git+ location: git://github.com/TobBrandt/data-flagset.git