packages feed

lhc-0.6.20081127: src/Util/SetLike.hs

module Util.SetLike(
    EnumSet(),
    (\\),
    notMember,
    mnotMember,
    minsert,
    msingleton,
    intersects,
    mfindWithDefault,
    SetLike(..),
    ModifySet(..),
    MapLike(..),
    BuildSet(..)
    ) where


import Data.Monoid
import Data.Typeable
import qualified Data.IntMap as IM
import qualified Data.IntSet as IS
import qualified Data.Map as M
import qualified Data.Set as S

import Util.HasSize

infixl 9 \\ --

m1 \\ m2 = difference m1 m2

class (HasSize s,IsEmpty s) => SetLike s where
    difference :: s -> s -> s
    intersection :: s -> s -> s
    disjoint :: s -> s -> Bool
    isSubsetOf :: s -> s -> Bool

    union :: s -> s -> s
    unions :: [s] -> s
    sempty :: s

    disjoint x y = isEmpty (x `intersection` y)
    isSubsetOf x y = size x <= size y && (size (x `intersection` y) == size x)
    unions ss = foldr union sempty ss


-- you can't pull values out of the set with this, as it might store the
-- essence of a data type

class SetLike s => BuildSet t s | s -> t where
    fromList :: [t] -> s
    fromDistinctAscList :: [t] -> s
    insert :: t -> s -> s
    singleton :: t -> s

    singleton t = fromDistinctAscList [t]
    fromDistinctAscList = fromList

class BuildSet t s => ModifySet t s | s -> t where
    toList :: s -> [t]
    delete :: t -> s -> s
    member :: t -> s -> Bool
    sfilter :: (t -> Bool) -> s -> s

notMember x t = not $ member x t
mnotMember x t = not $ mmember x t

intersects x y = not $ disjoint x y


--  int set

instance SetLike IS.IntSet where
    difference = IS.difference
    intersection = IS.intersection
    isSubsetOf = IS.isSubsetOf
    union      = IS.union
    unions     = IS.unions
    sempty      = IS.empty

instance BuildSet Int IS.IntSet where
    fromList xs = IS.fromList xs
    fromDistinctAscList xs = IS.fromDistinctAscList xs
    insert x s = IS.insert x s
    singleton x = IS.singleton x

instance ModifySet Int IS.IntSet where
    toList s   = IS.toList s
    delete x s = IS.delete x s
    member x s = IS.member x s
    sfilter    = IS.filter

-- normal set

instance Ord a => SetLike (S.Set a) where
    difference = S.difference
    intersection = S.intersection
    isSubsetOf = S.isSubsetOf
    union      = S.union
    unions     = S.unions
    sempty      = S.empty

instance Ord a => BuildSet a (S.Set a) where
    fromList xs = S.fromList xs
    fromDistinctAscList xs = S.fromDistinctAscList xs
    insert x s = S.insert x s
    singleton x = S.singleton x

instance Ord a => ModifySet a (S.Set a) where
    toList s   = S.toList s
    member x s = S.member x s
    delete x s = S.delete x s
    sfilter    = S.filter

-- maps

instance SetLike (IM.IntMap a) where    -- SIC
    difference = IM.difference
    intersection = IM.intersection
    union      = IM.union
    unions     = IM.unions
    sempty     = IM.empty


instance BuildSet (Int,a) (IM.IntMap a) where
    fromList xs = IM.fromList xs
    fromDistinctAscList xs = IM.fromDistinctAscList xs
    insert (k,v) s = IM.insert k v s
    singleton (k,v) = IM.singleton k v


instance Ord a => SetLike (M.Map a b) where
    difference = M.difference
    intersection = M.intersection
    union      = M.union
    unions     = M.unions
    sempty     = M.empty

instance Ord a => BuildSet (a,b) (M.Map a b) where
    fromList xs = M.fromList xs
    fromDistinctAscList xs = M.fromDistinctAscList xs
    insert (k,v) s = M.insert k v s
    singleton (k,v) = M.singleton k v

minsert :: BuildSet (k,v) s => k -> v -> s -> s
minsert k v s = insert (k,v) s

msingleton :: BuildSet (k,v) s => k -> v -> s
msingleton k v = singleton (k,v)


class SetLike m => MapLike k v m | m -> k v where
    mdelete :: k -> m -> m
    mmember :: k -> m -> Bool
    mlookup :: k -> m -> Maybe v
    melems :: m -> [v]
    massocs :: m -> [(k,v)]
    mkeys :: m -> [k]
    mmapWithKey :: (k -> v -> v) -> m -> m
    mfilter :: (v -> Bool) -> m -> m
    mfilterWithKey :: (k -> v -> Bool) -> m -> m
    munionWith :: (v -> v -> v) -> m -> m -> m
    mpartitionWithKey :: (k -> v -> Bool) -> m -> (m,m)

    mkeys = map fst . massocs
    melems = map snd . massocs

instance MapLike Int a (IM.IntMap a) where
    mdelete = IM.delete
    mmember = IM.member
    mlookup k m = IM.lookup k m
    melems = IM.elems
    mkeys = IM.keys
    massocs = IM.toList
    mfilter = IM.filter
    mmapWithKey = IM.mapWithKey
    mfilterWithKey = IM.filterWithKey
    munionWith = IM.unionWith
    mpartitionWithKey = IM.partitionWithKey

instance Ord k => MapLike k v (M.Map k v) where
    mdelete = M.delete
    mmember = M.member
    mlookup = M.lookup
    melems = M.elems
    mkeys = M.keys
    massocs = M.toList
    mfilter = M.filter
    mmapWithKey = M.mapWithKey
    mfilterWithKey = M.filterWithKey
    munionWith = M.unionWith
    mpartitionWithKey = M.partitionWithKey

mfindWithDefault d k m = case mlookup k m of
    Nothing -> d
    Just x -> x

-- EnumSet

newtype EnumSet a = EnumSet IS.IntSet
    deriving(Typeable,Monoid,SetLike,HasSize,Eq,Ord,IsEmpty)

instance Enum a => BuildSet a (EnumSet a) where
    fromList xs = EnumSet $ IS.fromList (map fromEnum xs)
    fromDistinctAscList xs = EnumSet $ IS.fromDistinctAscList (map fromEnum xs)
    insert x (EnumSet s) = EnumSet $ IS.insert (fromEnum x) s
    singleton x = EnumSet $ IS.singleton (fromEnum x)

instance Enum a => ModifySet a (EnumSet a) where
    toList (EnumSet s) = map toEnum $ toList s
    member x (EnumSet s) = IS.member (fromEnum x) s
    delete x (EnumSet s) = EnumSet $ IS.delete (fromEnum x) s
    sfilter f (EnumSet s) = EnumSet $ IS.filter (f . toEnum)  s