{-# LANGUAGE DeriveDataTypeable #-}
module Data.Generics.Uniplate.Data.Instances(
Hide(..), Trigger(..), Invariant(..),
Map, fromMap, toMap,
Set, fromSet, toSet,
IntMap, fromIntMap, toIntMap,
IntSet, fromIntSet, toIntSet
) where
import Data.Data
import qualified Data.Map as Map
import qualified Data.Set as Set
import qualified Data.IntMap as IntMap
import qualified Data.IntSet as IntSet
newtype Hide a = Hide {fromHide :: a}
deriving (Read,Ord,Eq,Typeable)
instance Show a => Show (Hide a) where
show (Hide a) = "Hide " ++ show a
instance Functor Hide where
fmap f (Hide x) = Hide $ f x
instance Typeable a => Data (Hide a) where
gfoldl k z x = z x
gunfold k z c = error "Data.Generics.Uniplate.Data.Instances.Hide: gunfold not implemented - data type has no constructors"
toConstr _ = error "Data.Generics.Uniplate.Data.Instances.Hide: toConstr not implemented - data type has no constructors"
dataTypeOf _ = tyHide
tyHide = mkDataType "Data.Generics.Uniplate.Data.Instances.Hide" []
data Trigger a = Trigger {trigger :: Bool, fromTrigger :: a}
deriving (Read,Ord,Eq,Show,Typeable)
instance Functor Trigger where
fmap f (Trigger a b) = Trigger a $ f b
instance (Data a, Typeable a) => Data (Trigger a) where
gfoldl k z (Trigger _ x) = z (Trigger True) `k` x
gunfold k z c = k $ z $ Trigger True
toConstr Trigger{} = conTrigger
dataTypeOf _ = tyTrigger
conTrigger = mkConstr tyTrigger "Trigger" [] Prefix
tyTrigger = mkDataType "Data.Generics.Uniplate.Data.Instances.Trigger" [conTrigger]
data Invariant a = Invariant {invariant :: a -> a, fromInvariant :: a}
deriving Typeable
instance Show a => Show (Invariant a) where
show (Invariant _ x) = "Invariant " ++ show x
instance (Data a, Typeable a) => Data (Invariant a) where
gfoldl k z (Invariant f x) = z (Invariant f . f) `k` x
gunfold k z c = k $ z $ \x -> Invariant (error msg) (error msg `asTypeOf` x)
where msg = "Data.Generics.Uniplate.Data.Instances.Invariant: gunfold only partially implemented"
toConstr Invariant{} = conInvariant
dataTypeOf _ = tyInvariant
conInvariant = mkConstr tyInvariant "Invariant" [] Prefix
tyInvariant = mkDataType "Data.Generics.Uniplate.Data.Instances.Invariant" [conInvariant]
newtype Map k v = Map (Invariant (Trigger [k], Trigger [v], Hide (Map.Map k v)))
deriving (Data, Typeable)
instance (Show k, Show v) => Show (Map k v) where; show = show . fromMap
instance (Eq k, Eq v) => Eq (Map k v) where; a == b = fromMap a == fromMap b
instance (Ord k, Ord v) => Ord (Map k v) where; compare a b = compare (fromMap a) (fromMap b)
fromMap :: Map k v -> Map.Map k v
fromMap (Map (Invariant _ (_,_,Hide x))) = x
toMap :: Ord k => Map.Map k v -> Map k v
toMap x = Map $ Invariant inv $ create x
where
create x = (Trigger False ks, Trigger False vs, Hide x)
where (ks,vs) = unzip $ Map.toAscList x
inv (ks,vs,x)
| trigger ks = create $ Map.fromList $ zip (fromTrigger ks) (fromTrigger vs)
| trigger vs = create $ Map.fromDistinctAscList $ zip (fromTrigger ks) (fromTrigger vs)
| otherwise = (ks,vs,x)
newtype Set k = Set (Invariant (Trigger [k], Hide (Set.Set k)))
deriving (Data, Typeable)
instance Show k => Show (Set k) where; show = show . fromSet
instance Eq k => Eq (Set k) where; a == b = fromSet a == fromSet b
instance Ord k => Ord (Set k) where; compare a b = compare (fromSet a) (fromSet b)
fromSet :: Set k -> Set.Set k
fromSet (Set (Invariant _ (_,Hide x))) = x
toSet :: Ord k => Set.Set k -> Set k
toSet x = Set $ Invariant inv $ create x
where
create x = (Trigger False $ Set.toList x, Hide x)
inv (ks,x)
| trigger ks = create $ Set.fromList $ fromTrigger ks
| otherwise = (ks,x)
newtype IntMap v = IntMap (Invariant (Trigger [Int], Trigger [v], Hide (IntMap.IntMap v)))
deriving (Data, Typeable)
instance Show v => Show (IntMap v) where; show = show . fromIntMap
instance Eq v => Eq (IntMap v) where; a == b = fromIntMap a == fromIntMap b
instance Ord v => Ord (IntMap v) where; compare a b = compare (fromIntMap a) (fromIntMap b)
fromIntMap :: IntMap v -> IntMap.IntMap v
fromIntMap (IntMap (Invariant _ (_,_,Hide x))) = x
toIntMap :: IntMap.IntMap v -> IntMap v
toIntMap x = IntMap $ Invariant inv $ create x
where
create x = (Trigger False ks, Trigger False vs, Hide x)
where (ks,vs) = unzip $ IntMap.toAscList x
inv (ks,vs,x)
| trigger ks = create $ IntMap.fromList $ zip (fromTrigger ks) (fromTrigger vs)
| trigger vs = create $ IntMap.fromDistinctAscList $ zip (fromTrigger ks) (fromTrigger vs)
| otherwise = (ks,vs,x)
newtype IntSet = IntSet (Invariant (Trigger [Int], Hide (IntSet.IntSet)))
deriving (Data, Typeable)
instance Show IntSet where; show = show . fromIntSet
instance Eq IntSet where; a == b = fromIntSet a == fromIntSet b
instance Ord IntSet where; compare a b = compare (fromIntSet a) (fromIntSet b)
fromIntSet :: IntSet -> IntSet.IntSet
fromIntSet (IntSet (Invariant _ (_,Hide x))) = x
toIntSet :: IntSet.IntSet -> IntSet
toIntSet x = IntSet $ Invariant inv $ create x
where
create x = (Trigger False $ IntSet.toList x, Hide x)
inv (ks,x)
| trigger ks = create $ IntSet.fromList $ fromTrigger ks
| otherwise = (ks,x)