{-# LANGUAGE DataKinds #-} {-# LANGUAGE PolyKinds #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE FlexibleInstances #-} -- | See for -- the original term-level code by Stefan Kahrs. -- -- @since 0.1.1.0 module Type.RBSet ( -- * Core type TypeSet (..) , Empty -- * Set operations , Member , Insertable(Insert) , InsertAll , FromList , Removable(Remove) , Merge ) where import Type.Compare import GHC.TypeLits -- | The color of a node. data Color = R | B deriving (Show,Eq) -- | A Red-Black tree. -- -- @since 0.1.1.0 data TypeSet a = E | N Color (TypeSet a) a (TypeSet a) deriving (Show,Eq) -- | A map without entries. type Empty = E -- -- -- Insertion {- | Insert a list of type level key / value pairs into a type-level map. -} type family InsertAll (es :: [k]) (t :: TypeSet k) :: TypeSet k where InsertAll '[] t = t InsertAll ( v ': es ) t = Insert v (InsertAll es t) {- | Build a type-level map out of a list of type level key / value pairs. -} type FromList (es :: [k]) = InsertAll es Empty {- | The associated type family 'Insert' produces the resulting map. -} class Insertable (k :: ki) (t :: TypeSet ki) where type Insert k t :: TypeSet ki -- insert x s = -- T B a z b -- where -- T _ a z b = ins s instance (InsertableHelper1 k t, Insert1 k t ~ inserted, CanMakeBlack inserted) => Insertable k t where type Insert k t = MakeBlack (Insert1 k t) class CanMakeBlack (t :: TypeSet ki) where type MakeBlack t :: TypeSet ki instance CanMakeBlack (N color left k right) where type MakeBlack (N color left k right) = N B left k right instance CanMakeBlack E where type MakeBlack E = E class InsertableHelper1 (k :: ki) (t :: TypeSet ki) where type Insert1 k t :: TypeSet ki instance InsertableHelper1 k E where type Insert1 k E = N R E k E instance (CmpType k k' ~ ordering, InsertableHelper2 ordering k color left k' right ) => InsertableHelper1 k (N color left k' right) where -- FIXME possible duplicate work with CmpType: both in constraint and in associated type family. -- Is that bad? How to avoid it? type Insert1 k (N color left k' right) = Insert2 (CmpType k k') k color left k' right class InsertableHelper2 (ordering :: Ordering) (k :: ki) (color :: Color) (left :: TypeSet ki) (k' :: ki) (right :: TypeSet ki) where type Insert2 ordering k color left k' right :: TypeSet ki -- ins s@(T B a y b) -- | x InsertableHelper2 LT k B left k' right where type Insert2 LT k B left k' right = Balance (Insert1 k left) k' right -- ins s@(T B a y b) -- | x InsertableHelper2 LT k R left k' right where type Insert2 LT k R left k' right = N R (Insert1 k left) k' right instance InsertableHelper2 EQ k color left k right where type Insert2 EQ k color left k right = N color left k right -- ins s@(T B a y b) -- | ... -- | x>y = balance a y (ins b) instance (InsertableHelper1 k right, Insert1 k right ~ inserted, Balanceable left k' inserted ) => InsertableHelper2 GT k B left k' right where type Insert2 GT k B left k' right = Balance left k' (Insert1 k right) -- ins s@(T R a y b) -- | ... -- | x>y = T R a y (ins b) instance (InsertableHelper1 k right, Insert1 k right ~ inserted, Balanceable left k' inserted ) => InsertableHelper2 GT k R left k' right where type Insert2 GT k R left k' right = N R left k' (Insert1 k right) data BalanceAction = BalanceSpecial | BalanceLL | BalanceLR | BalanceRL | BalanceRR | DoNotBalance deriving Show type family ShouldBalance (left :: TypeSet ki) (right :: TypeSet ki) :: BalanceAction where ShouldBalance (N R _ _ _) (N R _ _ _) = BalanceSpecial ShouldBalance (N R (N R _ _ _) _ _) _ = BalanceLL ShouldBalance (N R _ _ (N R _ _ _)) _ = BalanceLR ShouldBalance _ (N R (N R _ _ _) _ _) = BalanceRL ShouldBalance _ (N R _ _ (N R _ _ _)) = BalanceRR ShouldBalance _ _ = DoNotBalance class Balanceable (left :: TypeSet ki) (k :: ki) (right :: TypeSet ki) where type Balance left k right :: TypeSet ki instance (ShouldBalance left right ~ action, BalanceableHelper action left k right ) => Balanceable left k right where -- FIXME possible duplicate work with ShouldBalance: both in constraint and in associated type family. -- Is that bad? How to avoid it? type Balance left k right = Balance' (ShouldBalance left right) left k right class BalanceableHelper (action :: BalanceAction) (left :: TypeSet ki) (k :: ki) (right :: TypeSet ki) where type Balance' action left k right :: TypeSet ki -- balance (T R a x b) y (T R c z d) = T R (T B a x b) y (T B c z d) instance BalanceableHelper BalanceSpecial (N R left1 k1 right1) kx (N R left2 k2 right2) where type Balance' BalanceSpecial (N R left1 k1 right1) kx (N R left2 k2 right2) = N R (N B left1 k1 right1) kx (N B left2 k2 right2) -- balance (T R (T R a x b) y c) z d = T R (T B a x b) y (T B c z d) instance BalanceableHelper BalanceLL (N R (N R a k1 b) k2 c) k3 d where type Balance' BalanceLL (N R (N R a k1 b) k2 c) k3 d = N R (N B a k1 b) k2 (N B c k3 d) -- balance (T R a x (T R b y c)) z d = T R (T B a x b) y (T B c z d) instance BalanceableHelper BalanceLR (N R a k1 (N R b k2 c)) k3 d where type Balance' BalanceLR (N R a k1 (N R b k2 c)) k3 d = N R (N B a k1 b) k2 (N B c k3 d) -- balance a x (T R (T R b y c) z d) = T R (T B a x b) y (T B c z d) instance BalanceableHelper BalanceRL a k1 (N R (N R b k2 c) k3 d) where type Balance' BalanceRL a k1 (N R (N R b k2 c) k3 d) = N R (N B a k1 b) k2 (N B c k3 d) -- balance a x (T R b y (T R c z d)) = T R (T B a x b) y (T B c z d) instance BalanceableHelper BalanceRR a k1(N R b k2 (N R c k3 d)) where type Balance' BalanceRR a k1(N R b k2 (N R c k3 d)) = N R (N B a k1 b) k2 (N B c k3 d) -- balance a x b = T B a x b instance BalanceableHelper DoNotBalance a k b where type Balance' DoNotBalance a k b = N B a k b --- Member --- --- ------------------------------------------------------------------------------ -- | /O(log n)/. Determine membership in the 'TypeSet.' type family Member (t :: k) (bst :: TypeSet k) :: Bool where Member t 'E = 'False Member t ('N _ lbst a rbst) = MemberImpl (CmpType t a) t lbst rbst type family MemberImpl (ord :: Ordering) (t :: k) (lbst :: TypeSet k) (rbst :: TypeSet k) :: Bool where MemberImpl 'EQ t lbst rbst = 'True MemberImpl 'LT t lbst rbst = Member t lbst MemberImpl 'GT t lbst rbst = Member t rbst ------------------------------------------------------------------------------ -- | /O(m log n)/ for @Merge m n@; put your smaller set on the left side. Merge -- two 'TypeSet's together. type family Merge (small :: TypeSet k) (big :: TypeSet k) :: TypeSet k where Merge Empty big = big Merge small Empty = small Merge ('N _ lbst a rbst) big = Merge rbst (Merge lbst (Insert a big)) -- -- -- -- deletion -- -- -- type family DiscriminateBalL (l :: TypeSet ki) (r :: TypeSet ki) :: Bool where DiscriminateBalL (N R _ _ _) _ = False DiscriminateBalL _ _ = True class BalanceableL (l :: TypeSet ki) (k :: ki) (r :: TypeSet ki) where type BalL l k r :: TypeSet ki class BalanceableHelperL (b :: Bool) (l :: TypeSet ki) (k :: ki) (r :: TypeSet ki) where type BalL' b l k r :: TypeSet ki instance (DiscriminateBalL l r ~ b, BalanceableHelperL b l k r) => BalanceableL l k r where type BalL l k r = BalL' (DiscriminateBalL l r) l k r -- balleft :: RB a -> a -> RB a -> RB a -- balleft (T R a x b) y c = T R (T B a x b) y c instance BalanceableHelperL False (N R left1 k1 right1) k2 right2 where type BalL' False (N R left1 k1 right1) k2 right2 = (N R (N B left1 k1 right1) k2 right2) -- balleft bl x (T B a y b) = balance bl x (T R a y b) -- the @(N B in the call to balance tree is misleading, as it is ingored... instance (N R t2 z t3 ~ g, BalanceableHelper (ShouldBalance t1 g) t1 y g) => BalanceableHelperL True t1 y (N B t2 z t3) where type BalL' True t1 y (N B t2 z t3) = Balance t1 y (N R t2 z t3) -- balleft bl x (T R (T B a y b) z c) = T R (T B bl x a) y (balance b z (sub1 c)) instance (N R l k r ~ g, BalanceableHelper (ShouldBalance t3 g) t3 z g) => BalanceableHelperL True t1 y (N R (N B t2 u t3) z (N B l k r)) where type BalL' True t1 y (N R (N B t2 u t3) z (N B l k r)) = N R (N B t1 y t2) u (Balance t3 z (N R l k r)) -- balright :: RB a -> a -> RB a -> RB a -- balright a x (T R b y c) = T R a x (T B b y c) -- balright (T B a x b) y bl = balance (T R a x b) y bl -- balright (T R a x (T B b y c)) z bl = T R (balance (sub1 a) x b) y (T B c z bl) type family DiscriminateBalR (l :: TypeSet ki) (r :: TypeSet ki) :: Bool where DiscriminateBalR _ (N R _ _ _) = False DiscriminateBalR _ _ = True class BalanceableR (l :: TypeSet ki) (k :: ki) (r :: TypeSet ki) where type BalR l k r :: TypeSet ki class BalanceableHelperR (b :: Bool) (l :: TypeSet ki) (k :: ki) (r :: TypeSet ki) where type BalR' b l k r :: TypeSet ki instance (DiscriminateBalR l r ~ b, BalanceableHelperR b l k r) => BalanceableR l k r where type BalR l k r = BalR' (DiscriminateBalR l r) l k r -- balright :: RB a -> a -> RB a -> RB a -- balright a x (T R b y c) = T R a x (T B b y c) instance BalanceableHelperR False right2 k2 (N R left1 k1 right1) where type BalR' False right2 k2 (N R left1 k1 right1) = (N R right2 k2 (N B left1 k1 right1)) -- balright (T B a x b) y bl = balance (T R a x b) y bl instance (N R t2 z t3 ~ g, ShouldBalance g t1 ~ shouldbalance, BalanceableHelper shouldbalance g y t1) => BalanceableHelperR True (N B t2 z t3) y t1 where type BalR' True (N B t2 z t3) y t1 = Balance (N R t2 z t3) y t1 -- balright (T R a x (T B b y c)) z bl = T R (balance (sub1 a) x b) y (T B c z bl) instance (N R t2 u t3 ~ g, ShouldBalance g l ~ shouldbalance, BalanceableHelper shouldbalance g z l) => BalanceableHelperR True (N R (N B t2 u t3) z (N B l k r)) y t1 where type BalR' True (N R (N B t2 u t3) z (N B l k r)) y t1 = N R (Balance (N R t2 u t3) z l) k (N B r y t1) -- app :: RB a -> RB a -> RB a -- app E x = x -- app x E = x -- app (T R a x b) (T R c y d) = -- case app b c of -- T R b' z c' -> T R(T R a x b') z (T R c' y d) -- bc -> T R a x (T R bc y d) -- app (T B a x b) (T B c y d) = -- case app b c of -- T R b' z c' -> T R(T B a x b') z (T B c' y d) -- bc -> balleft a x (T B bc y d) -- app a (T R b x c) = T R (app a b) x c -- app (T R a x b) c = T R a x (app b c) class Fuseable (l :: TypeSet ki) (r :: TypeSet ki) where type Fuse l r :: TypeSet ki instance Fuseable E E where type Fuse E E = E -- app E x = x instance Fuseable E (N color left k right) where type Fuse E (N color left k right) = N color left k right -- app x E = x instance Fuseable (N color left k right) E where type Fuse (N color left k right) E = N color left k right -- app a (T R b x c) = T R (app a b) x c instance Fuseable (N B left1 k1 right1) left2 => Fuseable (N B left1 k1 right1) (N R left2 k2 right2) where type Fuse (N B left1 k1 right1) (N R left2 k2 right2) = N R (Fuse (N B left1 k1 right1) left2) k2 right2 -- app (T R a x b) c = T R a x (app b c) instance Fuseable right1 (N B left2 k2 right2) => Fuseable (N R left1 k1 right1) (N B left2 k2 right2) where type Fuse (N R left1 k1 right1) (N B left2 k2 right2) = N R left1 k1 (Fuse right1 (N B left2 k2 right2)) -- app (T R a x b) (T R c y d) = instance (Fuseable right1 left2, Fuse right1 left2 ~ fused, FuseableHelper1 fused (N R left1 k1 right1) (N R left2 k2 right2)) => Fuseable (N R left1 k1 right1) (N R left2 k2 right2) where type Fuse (N R left1 k1 right1) (N R left2 k2 right2) = Fuse1 (Fuse right1 left2) (N R left1 k1 right1) (N R left2 k2 right2) class FuseableHelper1 (fused :: TypeSet ki) (l :: TypeSet ki) (r :: TypeSet ki) where type Fuse1 fused l r :: TypeSet ki -- app (T R a x b) (T R c y d) = -- case app b c of -- T R b' z c' -> T R (T R a x b') z (T R c' y d) -- FIXME: The Fuseable constraint is repeated from avobe :( instance (Fuseable right1 left2, Fuse right1 left2 ~ N R s1 z s2) => FuseableHelper1 (N R s1 z s2) (N R left1 k1 right1) (N R left2 k2 right2) where type Fuse1 (N R s1 z s2) (N R left1 k1 right1) (N R left2 k2 right2) = N R (N R left1 k1 s1) z (N R s2 k2 right2) -- app (T R a x b) (T R c y d) = -- case app b c of -- ... -- bc -> T R a x (T R bc y d) -- FIXME: The Fuseable constraint is repeated from above :( instance (Fuseable right1 left2, Fuse right1 left2 ~ N B s1 z s2) => FuseableHelper1 (N B s1 z s2) (N R left1 k1 right1) (N R left2 k2 right2) where type Fuse1 (N B s1 z s2) (N R left1 k1 right1) (N R left2 k2 right2) = N R left1 k1 (N R (N B s1 z s2) k2 right2) -- app (T R a x b) (T R c y d) = -- case app b c of -- ... -- bc -> T R a x (T R bc y d) instance FuseableHelper1 E (N R left1 k1 E) (N R E k2 right2) where type Fuse1 E (N R left1 k1 E) (N R E k2 right2) = N R left1 k1 (N R E k2 right2) -- app (T B a x b) (T B c y d) = instance (Fuseable right1 left2, Fuse right1 left2 ~ fused, FuseableHelper2 fused (N B left1 k1 right1) (N B left2 k2 right2)) => Fuseable (N B left1 k1 right1) (N B left2 k2 right2) where type Fuse (N B left1 k1 right1) (N B left2 k2 right2) = Fuse2 (Fuse right1 left2) (N B left1 k1 right1) (N B left2 k2 right2) -- could FuseableHelper1 and FuseableHelper2 be, well... fused? class FuseableHelper2 (fused :: TypeSet ki) (l :: TypeSet ki) (r :: TypeSet ki) where type Fuse2 fused l r :: TypeSet ki -- app (T B a x b) (T B c y d) = -- case app b c of -- T R b' z c' -> T R (T B a x b') z (T B c' y d) instance (Fuseable right1 left2, Fuse right1 left2 ~ N R s1 z s2) => FuseableHelper2 (N R s1 z s2) (N B left1 k1 right1) (N B left2 k2 right2) where type Fuse2 (N R s1 z s2) (N B left1 k1 right1) (N B left2 k2 right2) = N R (N B left1 k1 s1) z (N B s2 k2 right2) -- app (T B a x b) (T B c y d) = -- case app b c of -- ... -- bc -> balleft a x (T B bc y d) instance (Fuseable right1 left2, Fuse right1 left2 ~ N B s1 z s2, BalanceableL left1 k1 (N B (N B s1 z s2) k2 right2)) => FuseableHelper2 (N B s1 z s2) (N B left1 k1 right1) (N B left2 k2 right2) where type Fuse2 (N B s1 z s2) (N B left1 k1 right1) (N B left2 k2 right2) = BalL left1 k1 (N B (N B s1 z s2) k2 right2) -- app (T B a x b) (T B c y d) = -- case app b c of -- ... -- bc -> balleft a x (T B bc y d) instance (BalanceableL left1 k1 (N B E k2 right2)) => FuseableHelper2 E (N B left1 k1 E) (N B E k2 right2) where type Fuse2 E (N B left1 k1 E) (N B E k2 right2) = BalL left1 k1 (N B E k2 right2) -- del E = E -- del (T _ a y b) -- | xy = delformRight a y b -- | otherwise = app a b class Delable (k :: ki) (t :: TypeSet ki) where type Del k t :: TypeSet ki -- delformLeft a@(T B _ _ _) y b = balleft (del a) y b -- delformLeft a y b = T R (del a) y b -- In the term-level code, the k to delete is already on the environment. class DelableL (k :: ki) (l :: TypeSet ki) (kx :: ki) (r :: TypeSet ki) where type DelL k l kx r :: TypeSet ki -- delformLeft a@(T B _ _ _) y b = balleft (del a) y b instance (N B leftz kz rightz ~ g, Delable k g, Del k g ~ deleted, BalanceableL deleted kx right) => DelableL k (N B leftz kz rightz) kx right where type DelL k (N B leftz kz rightz) kx right = BalL (Del k (N B leftz kz rightz)) kx right -- delformLeft a y b = T R (del a) y b instance (Delable k (N R leftz kz rightz)) => DelableL k (N R leftz kz rightz) kx right where type DelL k (N R leftz kz rightz) kx right = N R (Del k (N R leftz kz rightz)) kx right -- delformLeft a y b = T R (del a) y b instance DelableL k E kx right where type DelL k E kx right = N R E kx right -- delformRight a y b@(T B _ _ _) = balright a y (del b) -- delformRight a y b = T R a y (del b) class DelableR (k :: ki) (l :: TypeSet ki) (kx :: ki) (r :: TypeSet ki) where type DelR k l kx r :: TypeSet ki -- delformRight a y b@(T B _ _ _) = balright a y (del b) instance (N B leftz kz rightz ~ g, Delable k g, Del k g ~ deleted, BalanceableR left kx deleted) => DelableR k left kx (N B leftz kz rightz) where type DelR k left kx (N B leftz kz rightz) = BalR left kx (Del k (N B leftz kz rightz)) -- delformRight a y b = T R a y (del b) instance (Delable k (N R leftz kz rightz)) => DelableR k left kx (N R leftz kz rightz) where type DelR k left kx (N R leftz kz rightz) = N R left kx (Del k (N R leftz kz rightz)) -- delformRight a y b = T R a y (del b) instance DelableR k left kx E where type DelR k left kx E = N R left kx E -- del E = E instance Delable k E where type Del k E = E -- the color is discarded -- del (T _ a y b) -- | xy = delformRight a y b -- | otherwise = app a b instance (CmpType kx k ~ ordering, DelableHelper ordering k left kx right) => Delable k (N color left kx right) where type Del k (N color left kx right) = Del' (CmpType kx k) k left kx right class DelableHelper (ordering :: Ordering) (k :: ki) (l :: TypeSet ki) (kx :: ki) (r :: TypeSet ki) where type Del' ordering k l kx r :: TypeSet ki -- | x DelableHelper GT k left kx right where type Del' GT k left kx right = DelL k left kx right -- | otherwise = app a b instance Fuseable left right => DelableHelper EQ k left k right where type Del' EQ k left k right = Fuse left right -- | x>y = delformRight a y b instance DelableR k left kx right => DelableHelper LT k left kx right where type Del' LT k left kx right = DelR k left kx right {- | The associated type family 'Remove' produces the resulting map. -} class Removable (k :: ki) (t :: TypeSet ki) where type Remove k t :: TypeSet ki instance (Delable k t, Del k t ~ deleted, CanMakeBlack deleted) => Removable k t where type Remove k t = MakeBlack (Del k t) -- The original term-level code, taken from: -- https://www.cs.kent.ac.uk/people/staff/smk/redblack/rb.html -- -- {- Version 1, 'untyped' -} -- data Color = R | B deriving Show -- data RB a = E | T Color (RB a) a (RB a) deriving Show -- -- {- Insertion and membership test as by Okasaki -} -- insert :: Ord a => a -> RB a -> RB a -- insert x s = -- T B a z b -- where -- T _ a z b = ins s -- ins E = T R E x E -- ins s@(T B a y b) -- | xy = balance a y (ins b) -- | otherwise = s -- ins s@(T R a y b) -- | xy = T R a y (ins b) -- | otherwise = s -- -- -- {- balance: first equation is new, -- to make it work with a weaker invariant -} -- balance :: RB a -> a -> RB a -> RB a -- balance (T R a x b) y (T R c z d) = T R (T B a x b) y (T B c z d) -- balance (T R (T R a x b) y c) z d = T R (T B a x b) y (T B c z d) -- balance (T R a x (T R b y c)) z d = T R (T B a x b) y (T B c z d) -- balance a x (T R b y (T R c z d)) = T R (T B a x b) y (T B c z d) -- balance a x (T R (T R b y c) z d) = T R (T B a x b) y (T B c z d) -- balance a x b = T B a x b -- -- member :: Ord a => a -> RB a -> Bool -- member x E = False -- member x (T _ a y b) -- | xy = member x b -- | otherwise = True -- -- {- deletion a la SMK -} -- delete :: Ord a => a -> RB a -> RB a -- delete x t = -- case del t of {T _ a y b -> T B a y b; _ -> E} -- where -- del E = E -- del (T _ a y b) -- | xy = delformRight a y b -- | otherwise = app a b -- delformLeft a@(T B _ _ _) y b = balleft (del a) y b -- delformLeft a y b = T R (del a) y b -- -- delformRight a y b@(T B _ _ _) = balright a y (del b) -- delformRight a y b = T R a y (del b) -- -- balleft :: RB a -> a -> RB a -> RB a -- balleft (T R a x b) y c = T R (T B a x b) y c -- balleft bl x (T B a y b) = balance bl x (T R a y b) -- balleft bl x (T R (T B a y b) z c) = T R (T B bl x a) y (balance b z (sub1 c)) -- -- balright :: RB a -> a -> RB a -> RB a -- balright a x (T R b y c) = T R a x (T B b y c) -- balright (T B a x b) y bl = balance (T R a x b) y bl -- balright (T R a x (T B b y c)) z bl = T R (balance (sub1 a) x b) y (T B c z bl) -- -- sub1 :: RB a -> RB a -- sub1 (T B a x b) = T R a x b -- sub1 _ = error "invariance violation" -- -- app :: RB a -> RB a -> RB a -- app E x = x -- app x E = x -- app (T R a x b) (T R c y d) = -- case app b c of -- T R b' z c' -> T R (T R a x b') z (T R c' y d) -- bc -> T R a x (T R bc y d) -- app (T B a x b) (T B c y d) = -- case app b c of -- T R b' z c' -> T R(T B a x b') z (T B c' y d) -- bc -> balleft a x (T B bc y d) -- app a (T R b x c) = T R (app a b) x c -- app (T R a x b) c = T R a x (app b c)