edis (empty) → 0.0.1.0
raw patch · 18 files changed
+1213/−0 lines, 18 filesdep +basedep +bytestringdep +cerealsetup-changed
Dependencies added: base, bytestring, cereal, hedis
Files
- LICENSE +20/−0
- README.md +3/−0
- Setup.hs +2/−0
- edis.cabal +46/−0
- src/Database/Edis.hs +52/−0
- src/Database/Edis/Command.hs +60/−0
- src/Database/Edis/Command/Connection.hs +27/−0
- src/Database/Edis/Command/Hash.hs +63/−0
- src/Database/Edis/Command/Key.hs +104/−0
- src/Database/Edis/Command/List.hs +115/−0
- src/Database/Edis/Command/PubSub.hs +25/−0
- src/Database/Edis/Command/Scripting.hs +32/−0
- src/Database/Edis/Command/Server.hs +63/−0
- src/Database/Edis/Command/Set.hs +95/−0
- src/Database/Edis/Command/String.hs +111/−0
- src/Database/Edis/Command/ZSet.hs +147/−0
- src/Database/Edis/Helper.hs +57/−0
- src/Database/Edis/Type.hs +191/−0
+ LICENSE view
@@ -0,0 +1,20 @@+Copyright (c) 2015 Ting-Yen Lai++Permission is hereby granted, free of charge, to any person obtaining+a copy of this software and associated documentation files (the+"Software"), to deal in the Software without restriction, including+without limitation the rights to use, copy, modify, merge, publish,+distribute, sublicense, and/or sell copies of the Software, and to+permit persons to whom the Software is furnished to do so, subject to+the following conditions:++The above copyright notice and this permission notice shall be included+in all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ README.md view
@@ -0,0 +1,3 @@+# edis++Statically typechecked Redis
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ edis.cabal view
@@ -0,0 +1,46 @@+name: edis+version: 0.0.1.0+synopsis:+ Statically typechecked client for Redis+description:+ This library is a Haskell client for the Redis datastore built on top of+ Hedis, with stronger type-level guarantees.+ .+ For detailed documentation, see the "Database.Edis" module.+ .+license: MIT+license-file: LICENSE+author: Ting-Yan Lai+maintainer: banacorn@gmail.com+copyright: Copyright (c) 2015 Ting-Yan Lai+category: Database+build-type: Simple+extra-source-files: README.md+cabal-version: >=1.10++source-repository head+ type: git+ location: https://github.com/banacorn/edis++library+ exposed-modules: Database.Edis+ other-modules: Database.Edis.Type+ , Database.Edis.Helper+ , Database.Edis.Command+ , Database.Edis.Command.Key+ , Database.Edis.Command.String+ , Database.Edis.Command.List+ , Database.Edis.Command.Hash+ , Database.Edis.Command.Set+ , Database.Edis.Command.ZSet+ , Database.Edis.Command.Server+ , Database.Edis.Command.Connection+ , Database.Edis.Command.Scripting+ , Database.Edis.Command.PubSub+ build-depends: base >=4.8 && <5+ , bytestring >=0.10+ , hedis >=0.6+ , cereal >=0.4+ hs-source-dirs: src/+ default-language: Haskell2010+ GHC-Options: -Wall
+ src/Database/Edis.hs view
@@ -0,0 +1,52 @@+module Database.Edis (+ -- * How to use Edis+ -- |It's basically the same as in <https://hackage.haskell.org/package/hedis Hedis>.+ -- Most of the entities in Hedis are re-exported, or have the same names+ -- with types.+ --+ -- @+ -- -- connects to localhost:6379+ -- conn <- 'connect' 'defaultConnectInfo'+ -- @+ --+ -- Send commands to the server:+ --+ -- @+ -- {-\# LANGUAGE OverloadedStrings \#-}+ -- ...+ -- 'runRedis' conn $ 'unEdis' $ 'start'+ -- '`bind`' \_ -> 'set' ('Proxy' :: 'Proxy' \"hello\") True+ -- '`bind`' \_ -> 'set' ('Proxy' :: 'Proxy' \"world\") [True, False]+ -- '`bind`' \_ -> 'get' ('Proxy' :: 'Proxy' \"world\")+ -- @+ --+ -- Unfortunately 'Edis' is not a monad, so we can't use do-notations in+ -- the program. But the example above can be rewritten with '>>>' like+ -- this, if no variable bindings and result passings are needed.+ --+ -- @+ -- {-\# LANGUAGE OverloadedStrings \#-}+ -- ...+ -- 'runRedis' conn $ 'unEdis' $ 'start'+ -- '>>>' 'set' ('Proxy' :: 'Proxy' \"hello\") True+ -- '>>>' 'set' ('Proxy' :: 'Proxy' \"world\") [True, False]+ -- '>>>' 'get' ('Proxy' :: 'Proxy' \"world\")+ -- @+ --+ -- * Commands+ module Database.Edis.Command+ , Proxy(..)+ , Edis(..)+ , IMonad(..)+ , (>>>)++ , Redis.Reply+ , Redis.runRedis+ , Redis.connect+ , Redis.defaultConnectInfo+ ) where++import Data.Proxy+import qualified Database.Redis as Redis+import Database.Edis.Type+import Database.Edis.Command
+ src/Database/Edis/Command.hs view
@@ -0,0 +1,60 @@+{-# LANGUAGE DataKinds, TypeFamilies, TypeOperators, OverloadedStrings, PolyKinds #-}++module Database.Edis.Command (+ -- ** Keys+ module Database.Edis.Command.Key+ -- ** Strings+ , module Database.Edis.Command.String+ -- ** Lists+ , module Database.Edis.Command.List+ -- ** Hashes+ , module Database.Edis.Command.Hash+ -- ** Sets+ , module Database.Edis.Command.Set+ -- ** Sorted Sets+ , module Database.Edis.Command.ZSet+ -- ** Server+ , module Database.Edis.Command.Server+ -- ** Connection+ , module Database.Edis.Command.Connection+ -- ** Scripting+ , module Database.Edis.Command.Scripting+ -- ** Pub/Sub+ , module Database.Edis.Command.PubSub+ -- ** Assertions on types+ , start, declare, renounce+ ) where++import Database.Edis.Type+import Database.Edis.Command.Key+import Database.Edis.Command.String+import Database.Edis.Command.List+import Database.Edis.Command.Hash+import Database.Edis.Command.Set+import Database.Edis.Command.ZSet+import Database.Edis.Command.Server+import Database.Edis.Command.Connection+import Database.Edis.Command.Scripting+import Database.Edis.Command.PubSub++import Data.Proxy (Proxy)+import GHC.TypeLits++--------------------------------------------------------------------------------+-- Helper functions+--------------------------------------------------------------------------------++start :: Edis '[] '[] ()+start = Edis (return ())++--------------------------------------------------------------------------------+-- Declaration+--------------------------------------------------------------------------------++declare :: (KnownSymbol s, Member xs s ~ 'False)+ => Proxy s -> Proxy x -> Edis xs (Set xs s x) ()+declare _ _ = Edis $ return ()++renounce :: (KnownSymbol s, Member xs s ~ 'True)+ => Proxy s -> Edis xs (Del xs s) ()+renounce _ = Edis $ return ()
+ src/Database/Edis/Command/Connection.hs view
@@ -0,0 +1,27 @@+{-# LANGUAGE PolyKinds #-}++module Database.Edis.Command.Connection where++import Database.Edis.Type++import Data.ByteString (ByteString)+import Database.Redis as Redis hiding (decode)++--------------------------------------------------------------------------------+-- Connection+--------------------------------------------------------------------------------++auth :: ByteString -> Edis xs xs (Either Reply Status)+auth = Edis . Redis.auth++echo :: ByteString -> Edis xs xs (Either Reply ByteString)+echo = Edis . Redis.echo++ping :: Edis xs xs (Either Reply Status)+ping = Edis Redis.ping++quit :: Edis xs xs (Either Reply Status)+quit = Edis Redis.quit++select :: Integer -> Edis xs xs (Either Reply Status)+select = Edis . Redis.select
+ src/Database/Edis/Command/Hash.hs view
@@ -0,0 +1,63 @@+{-# LANGUAGE DataKinds, PolyKinds, TypeFamilies, TypeOperators, OverloadedStrings #-}++module Database.Edis.Command.Hash where++import Database.Edis.Type+import Database.Edis.Helper++import Data.ByteString (ByteString)+import Data.Proxy (Proxy)+import Data.Serialize (Serialize, encode)+import Data.Type.Bool+import Database.Redis as Redis hiding (decode)+import GHC.TypeLits++--------------------------------------------------------------------------------+-- Hashes+--------------------------------------------------------------------------------++hdel :: (KnownSymbol k, KnownSymbol f, HashOrNX xs k)+ => Proxy k -> Proxy f+ -> Edis xs (DelHash xs k f) (Either Reply Integer)+hdel key field = Edis $ Redis.hdel (encodeKey key) [encodeKey field]++hexists :: (KnownSymbol k, KnownSymbol f, HashOrNX xs k)+ => Proxy k -> Proxy f+ -> Edis xs xs (Either Reply Bool)+hexists key field = Edis $ Redis.hexists (encodeKey key) (encodeKey field)++hget :: (KnownSymbol k, KnownSymbol f, Serialize x+ , 'Just (StringOf x) ~ GetHash xs k f)+ => Proxy k -> Proxy f+ -> Edis xs xs (Either Reply (Maybe x))+hget key field = Edis $ Redis.hget (encodeKey key) (encodeKey field) >>= decodeAsMaybe++hincrby :: (KnownSymbol k, KnownSymbol f, HashOrNX xs k)+ => Proxy k -> Proxy f -> Integer+ -> Edis xs (SetHash xs k f Integer) (Either Reply Integer)+hincrby key field n = Edis $ Redis.hincrby (encodeKey key) (encodeKey field) n++hincrbyfloat :: (KnownSymbol k, KnownSymbol f, HashOrNX xs k)+ => Proxy k -> Proxy f -> Double+ -> Edis xs (SetHash xs k f Double) (Either Reply Double)+hincrbyfloat key field n = Edis $ Redis.hincrbyfloat (encodeKey key) (encodeKey field) n++hkeys :: (KnownSymbol k, HashOrNX xs k)+ => Proxy k+ -> Edis xs xs (Either Reply [ByteString])+hkeys key = Edis $ Redis.hkeys (encodeKey key)++hlen :: (KnownSymbol k, HashOrNX xs k)+ => Proxy k+ -> Edis xs xs (Either Reply Integer)+hlen key = Edis $ Redis.hlen (encodeKey key)++hset :: (KnownSymbol k, KnownSymbol f, Serialize x, HashOrNX xs k)+ => Proxy k -> Proxy f -> x+ -> Edis xs (SetHash xs k f (StringOf x)) (Either Reply Bool)+hset key field val = Edis $ Redis.hset (encodeKey key) (encodeKey field) (encode val)++hsetnx :: (KnownSymbol k, KnownSymbol f, Serialize x, HashOrNX xs k)+ => Proxy k -> Proxy f -> x+ -> Edis xs (If (MemHash xs k f) xs (SetHash xs k f (StringOf x))) (Either Reply Bool)+hsetnx key field val = Edis $ Redis.hsetnx (encodeKey key) (encodeKey field) (encode val)
+ src/Database/Edis/Command/Key.hs view
@@ -0,0 +1,104 @@+{-# LANGUAGE DataKinds, PolyKinds, TypeFamilies, TypeOperators, OverloadedStrings #-}++module Database.Edis.Command.Key where++import Database.Edis.Type+import Database.Edis.Helper++import Data.ByteString (ByteString)+import Data.Proxy (Proxy)+import Data.Serialize (Serialize)+import Data.Type.Bool+import Data.Type.Equality+import Database.Redis as Redis hiding (decode)+import GHC.TypeLits+++--------------------------------------------------------------------------------+-- Keys+--------------------------------------------------------------------------------++del :: KnownSymbol s => Proxy s -> Edis xs (Del xs s) (Either Reply Integer)+del key = Edis $ Redis.del [encodeKey key]++dump :: ByteString -> Edis xs xs (Either Reply ByteString)+dump key = Edis $ Redis.dump key++exists :: ByteString -> Edis xs xs (Either Reply Bool)+exists key = Edis $ Redis.exists key++expire :: ByteString -> Integer -> Edis xs xs (Either Reply Bool)+expire key n = Edis $ Redis.expire key n++expireat :: ByteString -> Integer -> Edis xs xs (Either Reply Bool)+expireat key n = Edis $ Redis.expireat key n++keys :: ByteString -> Edis xs xs (Either Reply [ByteString])+keys pattern = Edis $ Redis.keys pattern++migrate :: ByteString -> ByteString -> ByteString -> Integer -> Integer -> Edis xs xs (Either Reply Status)+migrate host port key destinationDb timeout = Edis $ Redis.migrate host port key destinationDb timeout++move :: ByteString -> Integer -> Edis xs xs (Either Reply Bool)+move key db = Edis $ Redis.move key db++objectRefcount :: ByteString -> Edis xs xs (Either Reply Integer)+objectRefcount key = Edis $ Redis.objectRefcount key++objectEncoding :: ByteString -> Edis xs xs (Either Reply ByteString)+objectEncoding key = Edis $ Redis.objectEncoding key++objectIdletime :: ByteString -> Edis xs xs (Either Reply Integer)+objectIdletime key = Edis $ Redis.objectIdletime key++persist :: ByteString -> Edis xs xs (Either Reply Bool)+persist key = Edis $ Redis.persist key++pexpire :: ByteString -> Integer -> Edis xs xs (Either Reply Bool)+pexpire key n = Edis $ Redis.pexpire key n++pexpireat :: ByteString -> Integer -> Edis xs xs (Either Reply Bool)+pexpireat key n = Edis $ Redis.pexpireat key n++pttl :: ByteString -> Edis xs xs (Either Reply Integer)+pttl key = Edis $ Redis.pttl key++randomkey :: Edis xs xs (Either Reply (Maybe ByteString))+randomkey = Edis $ Redis.randomkey++-- 1. the old key must exist+-- 2. the old key and the new key must be different+rename :: (KnownSymbol s, KnownSymbol t, Member xs s ~ 'True, Get xs s ~ 'Just x, (s == t) ~ 'False)+ => Proxy s -> Proxy t -> Edis xs (Set (Del xs s) t x) (Either Reply Status)+rename key key' = Edis $ Redis.rename (encodeKey key) (encodeKey key')++++-- 1. the old key must exist+-- 2. the old key and the new key must be different+-- 3. if the new key exists+-- then nothing happens+-- else the new key is removed+renamenx :: (KnownSymbol s, KnownSymbol t, Member xs s ~ 'True, Get xs s ~ 'Just x, (s == t) ~ 'False)+ => Proxy s -> Proxy t -> Edis xs (If (Member xs t) xs (Del xs s)) (Either Reply Bool)+renamenx key key' = Edis $ Redis.renamenx (encodeKey key) (encodeKey key')++restore :: ByteString -> Integer -> ByteString -> Edis xs xs (Either Reply Status)+restore key n val = Edis $ Redis.restore key n val++-- must be a List, a Set or a Sorted Set+sort :: (KnownSymbol s, Serialize x, Member xs s ~ 'True+ , (Get xs s == 'Just (ListOf x) || Get xs s == 'Just (SetOf x) || Get xs s == 'Just (ZSetOf x)) ~ 'True)+ => Proxy s -> SortOpts -> Edis xs xs (Either Reply [x])+sort key opt = Edis $ Redis.sort (encodeKey key) opt >>= decodeAsList++sortStore :: (KnownSymbol s, KnownSymbol t, Member xs s ~ 'True, FromJust (Get xs s) ~ x+ , (IsList (FromJust (Get xs s)) || IsSet (FromJust (Get xs s)) || IsZSet (FromJust (Get xs s))) ~ 'True)+ => Proxy s -> Proxy t -> SortOpts -> Edis xs (Set xs s x) (Either Reply Integer)+sortStore key dest opt = Edis $ Redis.sortStore (encodeKey key) (encodeKey dest) opt++ttl :: ByteString -> Edis xs xs (Either Reply Integer)+ttl key = Edis $ Redis.ttl key++getType :: ByteString -> Edis xs xs (Either Reply RedisType)+getType key = Edis $ Redis.getType key
+ src/Database/Edis/Command/List.hs view
@@ -0,0 +1,115 @@+{-# LANGUAGE DataKinds, PolyKinds, TypeFamilies, TypeOperators, OverloadedStrings #-}++module Database.Edis.Command.List where++import Database.Edis.Type+import Database.Edis.Helper++import Data.ByteString (ByteString)+import Data.Proxy (Proxy)+import Data.Serialize (Serialize, encode)+import Data.Type.Bool+import Database.Redis as Redis hiding (decode)+import GHC.TypeLits+++--------------------------------------------------------------------------------+-- List+--------------------------------------------------------------------------------++blpop :: (KnownSymbol s, Serialize x, ListOf x ~ FromJust (Get xs s))+ => Proxy s -> Integer+ -> Edis xs xs (Either Reply (Maybe (ByteString, x)))+blpop key timeout = Edis $ Redis.blpop [encodeKey key] timeout >>= decodeBPOP++brpop :: (KnownSymbol s, Serialize x, ListOf x ~ FromJust (Get xs s))+ => Proxy s -> Integer+ -> Edis xs xs (Either Reply (Maybe (ByteString, x)))+brpop key timeout = Edis $ Redis.brpop [encodeKey key] timeout >>= decodeBPOP++brpoplpush :: (KnownSymbol s, KnownSymbol t, Serialize x+ , ListOf x ~ FromJust (Get xs s), ListOrNX xs s)+ => Proxy s -> Proxy t -> Integer+ -> Edis xs (Set xs s (ListOf x)) (Either Reply (Maybe x))+brpoplpush key dest timeout = Edis $ Redis.brpoplpush (encodeKey key) (encodeKey dest) timeout >>= decodeAsMaybe++lindex :: (KnownSymbol s, Serialize x, ListOf x ~ FromJust (Get xs s))+ => Proxy s -> Integer+ -> Edis xs xs (Either Reply (Maybe x))+lindex key index = Edis $ Redis.lindex (encodeKey key) index >>= decodeAsMaybe++linsertBefore :: (KnownSymbol s, Serialize x, ListOrNX xs s)+ => Proxy s -> x -> x+ -> Edis xs xs (Either Reply Integer)+linsertBefore key pivot val = Edis $ Redis.linsertBefore (encodeKey key) (encode pivot) (encode val)++linsertAfter :: (KnownSymbol s, Serialize x, ListOrNX xs s)+ => Proxy s -> x -> x+ -> Edis xs xs (Either Reply Integer)+linsertAfter key pivot val = Edis $ Redis.linsertAfter (encodeKey key) (encode pivot) (encode val)++llen :: (KnownSymbol s, ListOrNX xs s)+ => Proxy s+ -> Edis xs xs (Either Reply Integer)+llen key = Edis $ Redis.llen (encodeKey key)++lpop :: (KnownSymbol s, Serialize x, 'Just (ListOf x) ~ Get xs s)+ => Proxy s+ -> Edis xs xs (Either Reply (Maybe x))+lpop key = Edis $ Redis.lpop (encodeKey key) >>= decodeAsMaybe++lpush :: (KnownSymbol s, Serialize x, ListOrNX xs s)+ => Proxy s -> x+ -> Edis xs (Set xs s (ListOf x)) (Either Reply Integer)+lpush key val = Edis $ Redis.lpush (encodeKey key) [encode val]++-- no operation will be performed when key does not yet exist.+lpushx :: (KnownSymbol s, Serialize x, 'Just (ListOf x) ~ Get xs s)+ => Proxy s -> x+ -> Edis xs xs (Either Reply Integer)+lpushx key val = Edis $ Redis.lpushx (encodeKey key) (encode val)++lrange :: (KnownSymbol s, Serialize x, ListOrNX xs s)+ => Proxy s -> Integer -> Integer+ -> Edis xs xs (Either Reply [x])+lrange key from to = Edis $ Redis.lrange (encodeKey key) from to >>= decodeAsList++lrem :: (KnownSymbol s, Serialize x, ListOrNX xs s)+ => Proxy s -> Integer -> x+ -> Edis xs xs (Either Reply Integer)+lrem key count val = Edis $ Redis.lrem (encodeKey key) count (encode val)++lset :: (KnownSymbol s, Serialize x, IsList (FromJust (Get xs s)) ~ 'True)+ => Proxy s -> Integer -> x+ -> Edis xs xs (Either Reply Status)+lset key index val = Edis $ Redis.lset (encodeKey key) index (encode val)++ltrim :: (KnownSymbol s, ListOrNX xs s)+ => Proxy s -> Integer -> Integer+ -> Edis xs xs (Either Reply Status)+ltrim key from to = Edis $ Redis.ltrim (encodeKey key) from to++rpop :: (KnownSymbol s, Serialize x, 'Just (ListOf x) ~ Get xs s)+ => Proxy s+ -> Edis xs xs (Either Reply (Maybe x))+rpop key = Edis $ Redis.rpop (encodeKey key) >>= decodeAsMaybe++-- 1. source and target must be List or does not yet exists+rpoplpush :: (KnownSymbol s, KnownSymbol t, Serialize x+ , ListOrNX xs s , ListOrNX xs t)+ => Proxy s -> Proxy t+ -> Edis xs (If (IsList (FromJust (Get xs s)))+ (Set xs s (ListOf x))+ xs) (Either Reply (Maybe x))+rpoplpush key dest = Edis $ Redis.rpoplpush (encodeKey key) (encodeKey dest) >>= decodeAsMaybe++rpush :: (KnownSymbol s, Serialize x, ListOrNX xs s)+ => Proxy s -> x+ -> Edis xs (Set xs s (ListOf x)) (Either Reply Integer)+rpush key val = Edis $ Redis.rpush (encodeKey key) [encode val]++-- no operation will be performed when key does not yet exist.+rpushx :: (KnownSymbol s, Serialize x, 'Just (ListOf x) ~ Get xs s)+ => Proxy s -> x+ -> Edis xs xs (Either Reply Integer)+rpushx key val = Edis $ Redis.rpushx (encodeKey key) (encode val)
+ src/Database/Edis/Command/PubSub.hs view
@@ -0,0 +1,25 @@+{-# LANGUAGE PolyKinds #-}++module Database.Edis.Command.PubSub (+ Database.Edis.Command.PubSub.publish+ , Database.Edis.Command.PubSub.pubSub+ , subscribe+ , unsubscribe+ , psubscribe+ , punsubscribe+) where++import Database.Edis.Type++import Data.ByteString (ByteString)+import Database.Redis as Redis hiding (decode)++--------------------------------------------------------------------------------+-- Pub/Sub+--------------------------------------------------------------------------------++publish :: ByteString -> ByteString -> Edis xs xs (Either Reply Integer)+publish channel message = Edis $ Redis.publish channel message++pubSub :: PubSub -> (Message -> IO PubSub) -> Edis xs xs ()+pubSub initSub callback = Edis $ Redis.pubSub initSub callback
+ src/Database/Edis/Command/Scripting.hs view
@@ -0,0 +1,32 @@+{-# LANGUAGE PolyKinds #-}++module Database.Edis.Command.Scripting where++import Database.Edis.Type++import Data.ByteString (ByteString)+import Database.Redis as Redis hiding (decode)++--------------------------------------------------------------------------------+-- Scripting+--------------------------------------------------------------------------------++eval :: (RedisResult a)+ => ByteString -> [ByteString] -> [ByteString] -> Edis xs xs (Either Reply a)+eval script keys' args = Edis $ Redis.eval script keys' args++evalsha :: (RedisResult a)+ => ByteString -> [ByteString] -> [ByteString] -> Edis xs xs (Either Reply a)+evalsha script keys' args = Edis $ Redis.evalsha script keys' args++scriptExists :: [ByteString] -> Edis xs xs (Either Reply [Bool])+scriptExists scripts = Edis $ Redis.scriptExists scripts++scriptFlush :: Edis xs xs (Either Reply Status)+scriptFlush = Edis $ Redis.scriptFlush++scriptKill :: Edis xs xs (Either Reply Status)+scriptKill = Edis $ Redis.scriptFlush++scriptLoad :: ByteString -> Edis xs xs (Either Reply ByteString)+scriptLoad script = Edis $ Redis.scriptLoad script
+ src/Database/Edis/Command/Server.hs view
@@ -0,0 +1,63 @@+{-# LANGUAGE PolyKinds #-}++module Database.Edis.Command.Server where++import Database.Edis.Type++import Data.ByteString (ByteString)+import Database.Redis as Redis hiding (decode)++--------------------------------------------------------------------------------+-- Server+--------------------------------------------------------------------------------++bgrewriteaof :: Edis xs xs (Either Reply Status)+bgrewriteaof = Edis $ Redis.bgrewriteaof++bgsave :: Edis xs xs (Either Reply Status)+bgsave = Edis $ Redis.bgsave++configGet :: ByteString -> Edis xs xs (Either Reply [(ByteString, ByteString)])+configGet param = Edis $ Redis.configGet param++configResetstat :: Edis xs xs (Either Reply Status)+configResetstat = Edis $ Redis.configResetstat++configSet :: ByteString -> ByteString -> Edis xs xs (Either Reply Status)+configSet param val = Edis $ Redis.configSet param val++dbsize :: Edis xs xs (Either Reply Integer)+dbsize = Edis $ Redis.dbsize++debugObject :: ByteString -> Edis xs xs (Either Reply ByteString)+debugObject key = Edis $ Redis.debugObject key++flushall :: Edis xs xs (Either Reply Status)+flushall = Edis $ Redis.flushall++flushdb :: Edis xs xs (Either Reply Status)+flushdb = Edis $ Redis.flushdb++info :: Edis xs xs (Either Reply ByteString)+info = Edis $ Redis.info++lastsave :: Edis xs xs (Either Reply Integer)+lastsave = Edis $ Redis.lastsave++save :: Edis xs xs (Either Reply Status)+save = Edis $ Redis.save++slaveof :: ByteString -> ByteString -> Edis xs xs (Either Reply Status)+slaveof host port = Edis $ Redis.slaveof host port++slowlogGet :: Integer -> Edis xs xs (Either Reply [Slowlog])+slowlogGet count = Edis $ Redis.slowlogGet count++slowlogLen :: Edis xs xs (Either Reply Integer)+slowlogLen = Edis $ Redis.slowlogLen++slowlogReset :: Edis xs xs (Either Reply Status)+slowlogReset = Edis $ Redis.slowlogReset++time :: Edis xs xs (Either Reply (Integer, Integer))+time = Edis $ Redis.time
+ src/Database/Edis/Command/Set.hs view
@@ -0,0 +1,95 @@+{-# LANGUAGE DataKinds, PolyKinds, TypeFamilies, TypeOperators, OverloadedStrings #-}++module Database.Edis.Command.Set where++import Database.Edis.Type+import Database.Edis.Helper++import Data.Proxy (Proxy)+import Data.Serialize (Serialize, encode)+import Data.Type.Bool+import Database.Redis as Redis hiding (decode)+import GHC.TypeLits++--------------------------------------------------------------------------------+-- Sets+--------------------------------------------------------------------------------++sadd :: (KnownSymbol s, Serialize x, SetOrNX xs s)+ => Proxy s -> x+ -> Edis xs (If (Member xs s) xs (Set xs s (SetOf x))) (Either Reply Integer)+sadd key val = Edis $ Redis.sadd (encodeKey key) [encode val]++scard :: (KnownSymbol s, SetOrNX xs s)+ => Proxy s+ -> Edis xs xs (Either Reply Integer)+scard key = Edis $ Redis.scard (encodeKey key)++sdiff :: (KnownSymbol s, KnownSymbol t, Serialize x+ , 'Just (SetOf x) ~ Get xs s -- must exist+ , SetOrNX xs s)+ => Proxy s -> Proxy t+ -> Edis xs xs (Either Reply [x])+sdiff key key' = Edis $ Redis.sdiff [encodeKey key, encodeKey key'] >>= decodeAsList++sdiffstore :: (KnownSymbol s, KnownSymbol t, SetOrNX xs s, SetOrNX xs t)+ => Proxy s -> Proxy t+ -> Edis xs xs (Either Reply Integer)+sdiffstore dest key = Edis $ Redis.sdiffstore (encodeKey dest) [encodeKey key]++sinter :: (KnownSymbol s, KnownSymbol t, Serialize x+ , 'Just (SetOf x) ~ Get xs s -- must exist+ , SetOrNX xs s)+ => Proxy s -> Proxy t+ -> Edis xs xs (Either Reply [x])+sinter key key' = Edis $ Redis.sinter [encodeKey key, encodeKey key'] >>= decodeAsList++sinterstore :: (KnownSymbol s, KnownSymbol t, SetOrNX xs s, SetOrNX xs t)+ => Proxy s -> Proxy t+ -> Edis xs xs (Either Reply Integer)+sinterstore dest key = Edis $ Redis.sinterstore (encodeKey dest) [encodeKey key]++smembers :: (KnownSymbol s, Serialize x+ , 'Just (SetOf x) ~ Get xs s)+ => Proxy s+ -> Edis xs xs (Either Reply [x])+smembers key = Edis $ Redis.smembers (encodeKey key) >>= decodeAsList++-- if the `dest` is not a set then the `src` must not exist+-- else the `src` and `dest` may be a set or does not exist.+smove :: (KnownSymbol s, KnownSymbol t, Serialize x+ , (Not (Member xs s) && Not (IsSet (FromJust (Get xs t)))+ || SetOrNX' xs s && SetOrNX' xs t) ~ 'True)+ => Proxy s -> Proxy t -> x -> Edis xs (Set xs t (SetOf x)) (Either Reply Bool)+smove src dest val = Edis $ Redis.smove (encodeKey src) (encodeKey dest) (encode val)++spop :: (KnownSymbol s, Serialize x+ , 'Just (SetOf x) ~ Get xs s)+ => Proxy s+ -> Edis xs xs (Either Reply (Maybe x))+spop key = Edis $ Redis.spop (encodeKey key) >>= decodeAsMaybe++srandmember :: (KnownSymbol s, Serialize x+ , 'Just (SetOf x) ~ Get xs s)+ => Proxy s+ -> Edis xs xs (Either Reply (Maybe x))+srandmember key = Edis $ Redis.srandmember (encodeKey key) >>= decodeAsMaybe++srem :: (KnownSymbol s, Serialize x+ , 'Just (SetOf x) ~ Get xs s)+ => Proxy s+ -> x+ -> Edis xs xs (Either Reply Integer)+srem key val = Edis $ Redis.srem (encodeKey key) [encode val]++sunion :: (KnownSymbol s, KnownSymbol t, Serialize x+ , 'Just (SetOf x) ~ Get xs s -- must exist+ , SetOrNX xs s)+ => Proxy s -> Proxy t+ -> Edis xs xs (Either Reply [x])+sunion key key' = Edis $ Redis.sunion [encodeKey key, encodeKey key'] >>= decodeAsList++sunionstore :: (KnownSymbol s, KnownSymbol t, SetOrNX xs s, SetOrNX xs t)+ => Proxy s -> Proxy t+ -> Edis xs xs (Either Reply Integer)+sunionstore dest key = Edis $ Redis.sunionstore (encodeKey dest) [encodeKey key]
+ src/Database/Edis/Command/String.hs view
@@ -0,0 +1,111 @@+{-# LANGUAGE DataKinds, PolyKinds, TypeFamilies, TypeOperators, OverloadedStrings #-}++module Database.Edis.Command.String where++import Database.Edis.Type+import Database.Edis.Helper++import Data.ByteString (ByteString)+import Data.Proxy (Proxy)+import Data.Serialize (Serialize, encode)+import Data.Type.Bool+import Database.Redis as Redis hiding (decode)+import GHC.TypeLits+++--------------------------------------------------------------------------------+-- String+--------------------------------------------------------------------------------++append :: (KnownSymbol s, Serialize x, StringOrNX xs s)+ => Proxy s -> x -> Edis xs (Set xs s (StringOf ByteString)) (Either Reply Integer)+append key val = Edis $ Redis.append (encodeKey key) (encode val)++bitcount :: (KnownSymbol s, StringOrNX xs s)+ => Proxy s -> Edis xs xs (Either Reply Integer)+bitcount key = Edis $ Redis.bitcount (encodeKey key)++bitcountRange :: (KnownSymbol s, StringOrNX xs s)+ => Proxy s -> Integer -> Integer -> Edis xs xs (Either Reply Integer)+bitcountRange key m n = Edis $ Redis.bitcountRange (encodeKey key) m n++-- key must be String or non-existent+bitopAnd :: (KnownSymbol s, KnownSymbol t, StringOrNX xs s)+ => Proxy t -> Proxy s -> Edis xs (Set xs s (StringOf ByteString)) (Either Reply Integer)+bitopAnd dest key = Edis $ Redis.bitopAnd (encodeKey dest) [encodeKey key]++bitopOr :: (KnownSymbol s, KnownSymbol t, StringOrNX xs s)+ => Proxy t -> Proxy s -> Edis xs (Set xs s (StringOf ByteString)) (Either Reply Integer)+bitopOr dest key = Edis $ Redis.bitopOr (encodeKey dest) [encodeKey key]++bitopXor :: (KnownSymbol s, KnownSymbol t, StringOrNX xs s)+ => Proxy t -> Proxy s -> Edis xs (Set xs s (StringOf ByteString)) (Either Reply Integer)+bitopXor dest key = Edis $ Redis.bitopXor (encodeKey dest) [encodeKey key]++bitopNot :: (KnownSymbol s, KnownSymbol t, StringOrNX xs s)+ => Proxy t -> Proxy s -> Edis xs (Set xs s (StringOf ByteString)) (Either Reply Integer)+bitopNot dest key = Edis $ Redis.bitopNot (encodeKey dest) (encodeKey key)++decr :: (KnownSymbol s, StringOfIntegerOrNX xs s)+ => Proxy s -> Edis xs (Set xs s (StringOf Integer)) (Either Reply Integer)+decr key = Edis $ Redis.decr (encodeKey key)++decrby :: (KnownSymbol s, StringOfIntegerOrNX xs s)+ => Proxy s -> Integer -> Edis xs (Set xs s (StringOf Integer)) (Either Reply Integer)+decrby key n = Edis $ Redis.decrby (encodeKey key) n++get :: (KnownSymbol s, Serialize x, StringOf x ~ FromJust (Get xs s))+ => Proxy s -> Edis xs xs (Either Reply (Maybe x))+get key = Edis $ Redis.get (encodeKey key) >>= decodeAsMaybe++getbit :: (KnownSymbol s, StringOrNX xs s)+ => Proxy s -> Integer -> Edis xs xs (Either Reply Integer)+getbit key n = Edis $ Redis.getbit (encodeKey key) n++getrange :: (KnownSymbol s, Serialize x, StringOf x ~ FromJust (Get xs s))+ => Proxy s -> Integer -> Integer -> Edis xs xs (Either Reply x)+getrange key n m = Edis $ Redis.getrange (encodeKey key) n m >>= decodeAsAnything++getset :: (KnownSymbol s, Serialize x, Serialize y, StringOf y ~ FromJust (Get xs s))+ => Proxy s -> x -> Edis xs xs (Either Reply (Maybe y))+getset key val = Edis $ Redis.getset (encodeKey key) (encode val) >>= decodeAsMaybe++incr :: (KnownSymbol s, StringOfIntegerOrNX xs s)+ => Proxy s -> Edis xs xs (Either Reply Integer)+incr key = Edis $ Redis.incr (encodeKey key)++incrby :: (KnownSymbol s, StringOfIntegerOrNX xs s)+ => Proxy s -> Integer -> Edis xs xs (Either Reply Integer)+incrby key n = Edis $ Redis.incrby (encodeKey key) n++incrbyfloat :: (KnownSymbol s, StringOfDoubleOrNX xs s)+ => Proxy s -> Double -> Edis xs xs (Either Reply Double)+incrbyfloat key n = Edis $ Redis.incrbyfloat (encodeKey key) n++psetex :: (KnownSymbol s, Serialize x)+ => Proxy s -> Integer -> x -> Edis xs (Set xs s (StringOf x)) (Either Reply Status)+psetex key n val = Edis $ Redis.psetex (encodeKey key) n (encode val)++set :: (KnownSymbol s, Serialize x)+ => Proxy s -> x -> Edis xs (Set xs s (StringOf x)) (Either Reply Status)+set key val = Edis $ Redis.set (encodeKey key) (encode val)++setbit :: (KnownSymbol s, Serialize x, StringOrNX xs s)+ => Proxy s -> Integer -> x -> Edis xs (Set xs s (StringOf x)) (Either Reply Integer)+setbit key n val = Edis $ Redis.setbit (encodeKey key) n (encode val)++setex :: (KnownSymbol s, Serialize x)+ => Proxy s -> Integer -> x -> Edis xs (Set xs s (StringOf x)) (Either Reply Status)+setex key n val = Edis $ Redis.setex (encodeKey key) n (encode val)++setnx :: (KnownSymbol s, Serialize x)+ => Proxy s -> x -> Edis xs (If (Member xs s) xs (Set xs s (StringOf x))) (Either Reply Bool)+setnx key val = Edis $ Redis.setnx (encodeKey key) (encode val)++setrange :: (KnownSymbol s, Serialize x, StringOrNX xs s)+ => Proxy s -> Integer -> x -> Edis xs (Set xs s (StringOf x)) (Either Reply Integer)+setrange key n val = Edis $ Redis.setrange (encodeKey key) n (encode val)++strlen :: (KnownSymbol s, StringOrNX xs s)+ => Proxy s -> Edis xs xs (Either Reply Integer)+strlen key = Edis $ Redis.strlen (encodeKey key)
+ src/Database/Edis/Command/ZSet.hs view
@@ -0,0 +1,147 @@+{-# LANGUAGE DataKinds, PolyKinds, TypeFamilies, TypeOperators, OverloadedStrings #-}++module Database.Edis.Command.ZSet where++import Database.Edis.Type+import Database.Edis.Helper++import Data.Proxy (Proxy)+import Data.Serialize (Serialize, encode)+import Data.Type.Bool+import Database.Redis as Redis hiding (decode)+import GHC.TypeLits++--------------------------------------------------------------------------------+-- Sorted Sets+--------------------------------------------------------------------------------++zadd :: (KnownSymbol s, Serialize x, ZSetOrNX xs s)+ => Proxy s -> Double -> x+ -> Edis xs (If (Member xs s) xs (Set xs s (ZSetOf x))) (Either Reply Integer)+zadd key score val = Edis $ Redis.zadd (encodeKey key) [(score, encode val)]+++zcard :: (KnownSymbol s, SetOrNX xs s)+ => Proxy s+ -> Edis xs xs (Either Reply Integer)+zcard key = Edis $ Redis.zcard (encodeKey key)++zcount :: (KnownSymbol s, SetOrNX xs s)+ => Proxy s -> Double -> Double+ -> Edis xs xs (Either Reply Integer)+zcount key min' max' = Edis $ Redis.zcount (encodeKey key) min' max'++zincrby :: (KnownSymbol s, Serialize x, ZSetOrNX xs s)+ => Proxy s -> Integer -> x+ -> Edis xs (If (Member xs s) xs (Set xs s (ZSetOf x))) (Either Reply Double)+zincrby key score val = Edis $ Redis.zincrby (encodeKey key) score (encode val)++zrange :: (KnownSymbol s, Serialize x+ , 'Just (ZSetOf x) ~ Get xs s)+ => Proxy s -> Integer -> Integer+ -> Edis xs xs (Either Reply [x])+zrange key from to = Edis $ Redis.zrange (encodeKey key) from to >>= decodeAsList++zrangeWithscores :: (KnownSymbol s, Serialize x+ , 'Just (ZSetOf x) ~ Get xs s)+ => Proxy s -> Integer -> Integer+ -> Edis xs xs (Either Reply [(x, Double)])+zrangeWithscores key from to =+ Edis $ Redis.zrangeWithscores (encodeKey key) from to >>= decodeAsListWithScores++zrangebyscore :: (KnownSymbol s, Serialize x+ , 'Just (ZSetOf x) ~ Get xs s)+ => Proxy s -> Double -> Double+ -> Edis xs xs (Either Reply [x])+zrangebyscore key min' max' =+ Edis $ Redis.zrangebyscore (encodeKey key) min' max' >>= decodeAsList++zrangebyscoreWithscores :: (KnownSymbol s, Serialize x+ , 'Just (ZSetOf x) ~ Get xs s)+ => Proxy s -> Double -> Double+ -> Edis xs xs (Either Reply [(x, Double)])+zrangebyscoreWithscores key min' max' =+ Edis $ Redis.zrangebyscoreWithscores (encodeKey key) min' max' >>= decodeAsListWithScores++zrangebyscoreLimit :: (KnownSymbol s, Serialize x+ , 'Just (ZSetOf x) ~ Get xs s)+ => Proxy s -> Double -> Double -> Integer -> Integer+ -> Edis xs xs (Either Reply [x])+zrangebyscoreLimit key min' max' offset count =+ Edis $ Redis.zrangebyscoreLimit (encodeKey key) min' max' offset count >>= decodeAsList++zrangebyscoreWithscoresLimit :: (KnownSymbol s, Serialize x+ , 'Just (ZSetOf x) ~ Get xs s)+ => Proxy s -> Double -> Double -> Integer -> Integer+ -> Edis xs xs (Either Reply [(x, Double)])+zrangebyscoreWithscoresLimit key min' max' offset count =+ Edis $ Redis.zrangebyscoreWithscoresLimit (encodeKey key) min' max' offset count >>= decodeAsListWithScores++zrank :: (KnownSymbol s, Serialize x+ , 'Just (ZSetOf x) ~ Get xs s)+ => Proxy s -> x+ -> Edis xs xs (Either Reply (Maybe Integer))+zrank key val = Edis $ Redis.zrank (encodeKey key) (encode val)++zremrangebyrank :: (KnownSymbol s, ZSetOrNX xs s)+ => Proxy s -> Integer -> Integer+ -> Edis xs xs (Either Reply Integer)+zremrangebyrank key from to = Edis $ Redis.zremrangebyrank (encodeKey key) from to++zremrangebyscore :: (KnownSymbol s, ZSetOrNX xs s)+ => Proxy s -> Double -> Double+ -> Edis xs xs (Either Reply Integer)+zremrangebyscore key min' max' = Edis $ Redis.zremrangebyscore (encodeKey key) min' max'++zrevrange :: (KnownSymbol s, Serialize x+ , 'Just (ZSetOf x) ~ Get xs s)+ => Proxy s -> Integer -> Integer+ -> Edis xs xs (Either Reply [x])+zrevrange key from to = Edis $ Redis.zrevrange (encodeKey key) from to >>= decodeAsList++zrevrangeWithscores :: (KnownSymbol s, Serialize x+ , 'Just (ZSetOf x) ~ Get xs s)+ => Proxy s -> Integer -> Integer+ -> Edis xs xs (Either Reply [(x, Double)])+zrevrangeWithscores key from to =+ Edis $ Redis.zrevrangeWithscores (encodeKey key) from to >>= decodeAsListWithScores++zrevrangebyscore :: (KnownSymbol s, Serialize x+ , 'Just (ZSetOf x) ~ Get xs s)+ => Proxy s -> Double -> Double+ -> Edis xs xs (Either Reply [x])+zrevrangebyscore key min' max' =+ Edis $ Redis.zrevrangebyscore (encodeKey key) min' max' >>= decodeAsList++zrevrangebyscoreWithscores :: (KnownSymbol s, Serialize x+ , 'Just (ZSetOf x) ~ Get xs s)+ => Proxy s -> Double -> Double+ -> Edis xs xs (Either Reply [(x, Double)])+zrevrangebyscoreWithscores key min' max' =+ Edis $ Redis.zrevrangebyscoreWithscores (encodeKey key) min' max' >>= decodeAsListWithScores++zrevrangebyscoreLimit :: (KnownSymbol s, Serialize x+ , 'Just (ZSetOf x) ~ Get xs s)+ => Proxy s -> Double -> Double -> Integer -> Integer+ -> Edis xs xs (Either Reply [x])+zrevrangebyscoreLimit key min' max' offset count =+ Edis $ Redis.zrevrangebyscoreLimit (encodeKey key) min' max' offset count >>= decodeAsList++zrevrangebyscoreWithscoresLimit :: (KnownSymbol s, Serialize x+ , 'Just (ZSetOf x) ~ Get xs s)+ => Proxy s -> Double -> Double -> Integer -> Integer+ -> Edis xs xs (Either Reply [(x, Double)])+zrevrangebyscoreWithscoresLimit key min' max' offset count =+ Edis $ Redis.zrevrangebyscoreWithscoresLimit (encodeKey key) min' max' offset count >>= decodeAsListWithScores++zrevrank :: (KnownSymbol s, Serialize x+ , 'Just (ZSetOf x) ~ Get xs s)+ => Proxy s -> x+ -> Edis xs xs (Either Reply (Maybe Integer))+zrevrank key val = Edis $ Redis.zrevrank (encodeKey key) (encode val)++zscore :: (KnownSymbol s, Serialize x+ , 'Just (ZSetOf x) ~ Get xs s)+ => Proxy s -> x+ -> Edis xs xs (Either Reply (Maybe Double))+zscore key val = Edis $ Redis.zscore (encodeKey key) (encode val)
+ src/Database/Edis/Helper.hs view
@@ -0,0 +1,57 @@+{-# OPTIONS_HADDOCK hide #-}++module Database.Edis.Helper where++import Data.ByteString (ByteString)+import Data.Maybe (fromJust)+import Data.Proxy (Proxy)+import Data.Serialize (Serialize, encode, decode)+import Database.Redis as Redis hiding (decode)+import GHC.TypeLits++--------------------------------------------------------------------------------+-- Helper functions+--------------------------------------------------------------------------------++encodeKey :: KnownSymbol s => Proxy s -> ByteString+encodeKey = encode . symbolVal++decodeAsAnything :: (Serialize x) => Either Reply ByteString -> Redis (Either Reply x)+decodeAsAnything (Left replyErr) = return $ Left replyErr+decodeAsAnything (Right str) = case decode str of+ Left decodeErr -> return $ Left (Error $ encode decodeErr)+ Right val -> return $ Right val++decodeAsMaybe :: (Serialize x) => Either Reply (Maybe ByteString) -> Redis (Either Reply (Maybe x))+decodeAsMaybe (Left replyErr) = return $ Left replyErr+decodeAsMaybe (Right Nothing) = return $ Right Nothing+decodeAsMaybe (Right (Just str)) = case decode str of+ Left decodeErr -> return $ Left (Error $ encode decodeErr)+ Right val -> return $ Right (Just val)++decodeBPOP :: Serialize x => Either Reply (Maybe (ByteString, ByteString)) -> Redis (Either Reply (Maybe (ByteString, x)))+decodeBPOP (Left replyError) = return $ Left replyError+decodeBPOP (Right Nothing) = return $ Right Nothing+decodeBPOP (Right (Just (key, raw))) = case decode raw of+ Left decodeError -> return $ Left (Error $ encode decodeError)+ Right value -> return $ Right (Just (key, value))++decodeAsList :: (Serialize x) => Either Reply [ByteString] -> Redis (Either Reply [x])+decodeAsList (Left replyErr) = return $ Left replyErr+decodeAsList (Right strs) = case mapM decode strs of+ Left decodeErr -> return $ Left (Error $ encode decodeErr)+ Right vals -> return $ Right vals++decodeAsListWithScores :: (Serialize x) => Either Reply [(ByteString, Double)] -> Redis (Either Reply [(x, Double)])+decodeAsListWithScores (Left replyErr) = return $ Left replyErr+decodeAsListWithScores (Right pairs) = let (strs, scores) = unzip pairs in+ case mapM decode strs of+ Left decodeErr -> return $ Left (Error $ encode decodeErr)+ Right vals -> return $ Right (zip vals scores)++fromRight :: Either a b -> b+fromRight (Left _) = error "Left val"+fromRight (Right e) = e++fromMaybeResult :: Either Reply (Maybe x) -> x+fromMaybeResult = fromJust . fromRight
+ src/Database/Edis/Type.hs view
@@ -0,0 +1,191 @@+{-# 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