{-# LANGUAGE UndecidableInstances, OverlappingInstances, FlexibleInstances,
             MultiParamTypeClasses, TemplateHaskell, PolymorphicComponents,
             DeriveDataTypeable,ExistentialQuantification #-}
module Data.IxSet.Ix
    ( Ix(..)
    , insert
    , delete
    , insertList
    , deleteList
    , union
    , intersection
    )
    where
import           Data.Generics hiding (GT)
import qualified Data.Generics.SYB.WithClass.Basics as SYBWC
import           Data.List  (foldl')
import           Data.Map   (Map)
import qualified Data.Map.Strict as Map
import           Data.Set   (Set)
import qualified Data.Set   as Set
data Ix a = forall key . (Typeable key, Ord key) =>
            Ix (Map key (Set a)) (a -> [key])
    deriving Typeable
 
instance Data a => Data (Ix a) where
    toConstr (Ix _ _) = con_Ix_Data
    gunfold _ _     = error "gunfold"
    dataTypeOf _    = ixType_Data
con_Ix_Data :: Constr
con_Ix_Data = mkConstr ixType_Data "Ix" [] Prefix
ixType_Data :: DataType
ixType_Data = mkDataType "Happstack.Data.IxSet.Ix" [con_Ix_Data]
ixConstr :: SYBWC.Constr
ixConstr = SYBWC.mkConstr ixDataType "Ix" [] SYBWC.Prefix
ixDataType :: SYBWC.DataType
ixDataType = SYBWC.mkDataType "Ix" [ixConstr]
instance (SYBWC.Typeable Ix, SYBWC.Data ctx a, SYBWC.Sat (ctx (Ix a)))
       => SYBWC.Data ctx (Ix a) where
    gfoldl _ _ _ _ = error "gfoldl Ix" :: w (Ix a)
    toConstr _ (Ix _ _)    = ixConstr
    gunfold _ _ _ _ = error "gunfold Ix" :: c (Ix a)
    dataTypeOf _ _ = ixDataType
insert :: (Ord a, Ord k)
       => k -> a -> Map k (Set a) -> Map k (Set a)
insert k v index = Map.insertWith Set.union k (Set.singleton v) index
insertList :: (Ord a, Ord k)
           => [(k,a)] -> Map k (Set a) -> Map k (Set a)
insertList xs index = foldl' (\m (k,v)-> insert k v m) index xs
delete :: (Ord a, Ord k)
       => k -> a -> Map k (Set a) -> Map k (Set a)
delete k v index = Map.update remove k index
    where
    remove set = let set' = Set.delete v set
                 in if Set.null set' then Nothing else Just set'
deleteList :: (Ord a, Ord k)
           => [(k,a)] -> Map k (Set a) -> Map k (Set a)
deleteList xs index = foldl' (\m (k,v) -> delete k v m) index xs
union :: (Ord a, Ord k)
       => Map k (Set a) -> Map k (Set a) -> Map k (Set a)
union index1 index2 = Map.unionWith Set.union index1 index2
intersection :: (Ord a, Ord k)
             => Map k (Set a) -> Map k (Set a) -> Map k (Set a)
intersection index1 index2 = Map.filter (not . Set.null) $
                             Map.intersectionWith Set.intersection index1 index2