{-# LANGUAGE DataKinds, ConstraintKinds, PolyKinds, TypeFamilies, TypeOperators #-} module Database.Edis.Type where import GHC.TypeLits import Data.Type.Bool import Data.Type.Equality import Database.Redis (Redis) -------------------------------------------------------------------------------- -- Maybe -------------------------------------------------------------------------------- -- FromJust : (Maybe k) -> k type family FromJust (x :: Maybe k) :: k where FromJust ('Just k) = k -------------------------------------------------------------------------------- -- Dictionary Membership -------------------------------------------------------------------------------- -- Member :: Key -> [ (Key, Type) ] -> Bool type family Member (xs :: [ (Symbol, *) ]) (s :: Symbol) :: Bool where Member '[] s = 'False Member ('(s, x) ': xs) s = 'True Member ('(t, x) ': xs) s = Member xs s -- memberEx0 :: (Member "C" '[] ~ False) => () -- memberEx0 = () -- -- memberEx1 :: (Member "A" '[ '("A", Char), '("B", Int) ] ~ True) => () -- memberEx1 = () -- -- memberEx2 :: (Member "C" '[ '("A", Char), '("B", Int) ] ~ False) => () -- memberEx2 = () -------------------------------------------------------------------------------- -- Dictionary Lookup -------------------------------------------------------------------------------- -- type family Get' (s :: Symbol) (xs :: [ (Symbol, *) ]) :: * where -- Get' s ('(s, x) ': xs) = x -- Get' s ('(t, x) ': xs) = Get' s xs -- -- getEx0' :: (Get' "A" '[ '("A", Char), '("B", Int) ] ~ Char) => () -- getEx0' = () -- -- getEx1' :: (Get' "C" '[ '("A", Char), '("B", Int) ] ~ Char) => () -- getEx1' = () -- Get :: Key -> [ (Key, Type) ] -> Maybe Type type family Get (xs :: [ (Symbol, *) ]) (s :: Symbol) :: Maybe * where Get '[] s = 'Nothing Get ('(s, x) ': xs) s = 'Just x Get ('(t, x) ': xs) s = Get xs s -- getEx0 :: (Get "A" '[ '("A", Char), '("B", Int) ] ~ Just Char) => () -- getEx0 = () -- -- getEx1 :: (Get "C" '[ '("A", Char), '("B", Int) ] ~ Nothing) => () -- getEx1 = () -------------------------------------------------------------------------------- -- Dictionary Set -------------------------------------------------------------------------------- -- Set :: Key -> Type -> [ (Key, Type) ] -> [ (Key, Type) ] type family Set (xs :: [ (Symbol, *) ]) (s :: Symbol) (x :: *) :: [ (Symbol, *) ] where Set '[] s x = '[ '(s, x) ] Set ('(s, y) ': xs) s x = ('(s, x) ': xs) Set ('(t, y) ': xs) s x = '(t, y) ': (Set xs s x) -- setEx0 :: (Set "A" Char '[] ~ '[ '("A", Char) ]) => () -- setEx0 = () -- -- setEx1 :: (Set "A" Bool '[ '("A", Char) ] ~ '[ '("A", Bool) ]) => () -- setEx1 = () -------------------------------------------------------------------------------- -- Dictionary Deletion -------------------------------------------------------------------------------- -- Del :: Key -> [ (Key, Type) ] -> [ (Key, Type) ] type family Del (xs :: [ (Symbol, *) ]) (s :: Symbol) :: [ (Symbol, *) ] where Del '[] s = '[] Del ('(s, y) ': xs) s = xs Del ('(t, y) ': xs) s = '(t, y) ': (Del xs s) -- delEx0 :: (Del "A" '[ '("A", Char) ] ~ '[]) => () -- delEx0 = () -- -- delEx1 :: (Del "A" '[ '("B", Int), '("A", Char) ] ~ '[ '("B", Int) ]) => () -- delEx1 = () -------------------------------------------------------------------------------- -- P -------------------------------------------------------------------------------- class IMonad m where unit :: a -> m p p a bind :: m p q a -> (a -> m q r b) -> m p r b newtype Edis p q a = Edis { unEdis :: Redis a } instance IMonad Edis where unit = Edis . return bind m f = Edis (unEdis m >>= unEdis . f ) infixl 1 >>> (>>>) :: IMonad m => m p q a -> m q r b -> m p r b a >>> b = bind a (const b) -------------------------------------------------------------------------------- -- Redis Data Types -------------------------------------------------------------------------------- data U n = String' n | Hash' n data StringOf :: * -> * data HashOf :: [ (Symbol, *) ] -> * data ListOf :: * -> * data SetOf :: * -> * data ZSetOf :: * -> * -------------------------------------------------------------------------------- -- Redis Data Type -------------------------------------------------------------------------------- type family IsString (x :: *) :: Bool where IsString (StringOf n) = 'True IsString x = 'False type StringOrNX xs s = (IsString (FromJust (Get xs s)) || Not (Member xs s)) ~ 'True type StringOfIntegerOrNX xs s = ((FromJust (Get xs s) == Integer) || Not (Member xs s)) ~ 'True type StringOfDoubleOrNX xs s = ((FromJust (Get xs s) == Double) || Not (Member xs s)) ~ 'True type family IsHash (x :: *) :: Bool where IsHash (HashOf n) = 'True IsHash x = 'False type HashOrNX xs k = (IsHash (FromJust (Get xs k)) || Not (Member xs k)) ~ 'True type family IsList (x :: *) :: Bool where IsList (ListOf n) = 'True IsList x = 'False type ListOrNX xs s = (IsList (FromJust (Get xs s)) || Not (Member xs s)) ~ 'True type family IsSet (x :: *) :: Bool where IsSet (SetOf n) = 'True IsSet x = 'False type SetOrNX xs s = (IsSet (FromJust (Get xs s)) || Not (Member xs s)) ~ 'True type SetOrNX' xs s = (IsSet (FromJust (Get xs s)) || Not (Member xs s)) type family IsZSet (x :: *) :: Bool where IsZSet (ZSetOf n) = 'True IsZSet x = 'False type ZSetOrNX xs s = (IsZSet (FromJust (Get xs s)) || Not (Member xs s)) ~ 'True type family GetHash (xs :: [ (Symbol, *) ]) (k :: Symbol) (f :: Symbol) :: Maybe * where GetHash '[] k f = 'Nothing GetHash ('(k, HashOf hs) ': xs) k f = Get hs f GetHash ('(k, x ) ': xs) k f = 'Nothing GetHash ('(l, y ) ': xs) k f = GetHash xs k f type family SetHash (xs :: [ (Symbol, *) ]) (k :: Symbol) (f :: Symbol) (x :: *) :: [ (Symbol, *) ] where SetHash '[] k f x = '(k, HashOf (Set '[] f x)) ': '[] SetHash ('(k, HashOf hs) ': xs) k f x = '(k, HashOf (Set hs f x)) ': xs SetHash ('(l, y ) ': xs) k f x = '(l, y ) ': SetHash xs k f x type family DelHash (xs :: [ (Symbol, *) ]) (k :: Symbol) (f :: Symbol) :: [ (Symbol, *) ] where DelHash '[] k f = '[] DelHash ('(k, HashOf hs) ': xs) k f = '(k, HashOf (Del hs f )) ': xs DelHash ('(l, y ) ': xs) k f = '(l, y ) ': DelHash xs k f type family MemHash (xs :: [ (Symbol, *) ]) (k :: Symbol) (f :: Symbol) :: Bool where MemHash '[] k f = 'False MemHash ('(k, HashOf hs) ': xs) k f = Member hs f MemHash ('(k, x ) ': xs) k f = 'False MemHash ('(l, y ) ': xs) k f = MemHash xs k f