edis-0.0.1.0: src/Database/Edis/Type.hs
{-# 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