Commits

Alvaro Videla committed 0d7eea9

first import

Comments (0)

Files changed (14)

Database/Redis.hs

+module Database.Redis where
+  
+import Database.Redis.Serializable
+import Database.Redis.Key
+
+import qualified Database.Redis.Strings as S
+import qualified Database.Redis.Keys as K
+import qualified Database.Redis.Lists as L
+-- import qualified Database.Redis.Sets as SS
+-- import qualified Database.Redis.Zsets as Z
+import qualified Database.Redis.RSCC as RSCC
+import qualified Database.Redis.Misc as Misc
+import qualified Database.Redis.DBM as DBM
+import qualified Database.Redis.Persistence as P
+
+import Database.Redis.Protocol(Server)
+
+class Redis a where
+  get :: (Key k, Serializable s) => 
+         a 
+      -> k 
+      -> IO (Maybe s)
+      
+  set :: (Key k, Serializable s) => 
+         a 
+      -> k 
+      -> s 
+      -> IO (Bool)
+      
+  setnx :: (Key k, Serializable s) => 
+           a 
+        -> k 
+        -> s 
+        -> IO (Bool)
+        
+  getset :: (Key k, Serializable s) => 
+            a 
+         -> k 
+         -> s 
+         -> IO (Maybe s)
+         
+  mget :: (Key k, Serializable s) => 
+          a 
+       -> [k] 
+       -> IO (Maybe [Maybe s])
+       
+  incr :: (Key k) => 
+          a 
+       -> k 
+       -> IO (Maybe Int)
+       
+  decr :: (Key k) => 
+          a 
+       -> k 
+       -> IO (Maybe Int)
+       
+  incrby :: (Key k) => 
+            a 
+         -> k 
+         -> Int 
+         -> 
+         IO (Maybe Int)
+         
+  decrby :: (Key k) => 
+            a 
+         -> k 
+         -> Int 
+         -> IO (Maybe Int)
+         
+  exists :: (Key k) => 
+            a 
+         -> k 
+         -> IO (Bool)
+         
+  del :: (Key k) => 
+         a 
+      -> k 
+      -> IO (Bool)
+      
+  rtype :: (Key k) => 
+           a 
+        -> k 
+        -> IO (Maybe String)
+        
+  keys :: a 
+       -> String 
+       -> IO (Maybe [String])
+       
+  randomkey :: a -> IO (Maybe String)
+            
+  rename :: (Key k) => 
+            a 
+         -> k 
+         -> k 
+         -> IO (Bool)
+         
+  renamenx :: (Key k) => 
+              a 
+           -> k 
+           -> k 
+           -> IO (Bool)
+  
+  dbsize :: a -> IO (Maybe Int)
+  
+  expire :: (Key k) => a -> k -> Int -> IO (Bool)
+         
+  ttl    :: (Key k) => a -> k -> IO (Maybe Int)
+         
+  lrange :: (Key k, Serializable s) => a -> k -> Int -> Int -> IO (Maybe [Maybe s])
+  lpush, rpush :: (Key k, Serializable s) => a -> k -> s -> IO (Bool)
+  llen :: (Key k) => a -> k -> IO (Maybe Int)
+  ltrim :: (Key k) => a -> k -> Int -> Int -> IO (Bool)
+  lindex :: (Key k, Serializable s) => a -> k -> Int -> IO (Maybe s)
+  lset :: (Key k, Serializable s) => a -> k -> Int -> s -> IO (Bool)
+  lrem :: (Key k, Serializable s) => a -> k -> Int -> s -> IO (Maybe Int)
+  lpop, rpop :: (Key k, Serializable s) => a -> k -> IO (Maybe s)
+  
+  -- sadd, srem :: (Key k, Serializable s) => a -> k -> s -> IO (Bool)
+  -- spop :: (Key k, Serializable s) => a -> k -> IO (Maybe s)
+  -- smove :: (Key k, Serializable s) => a -> k -> k -> s -> IO (Bool)
+  -- scard :: (Key k) => a -> k -> IO (Maybe Int)
+  -- sismember :: (Key k, Serializable s) => a -> k -> s -> IO (Bool)
+  -- sinter, sunion, sdiff :: (Key k, Serializable s) => a -> [k] -> IO (Maybe [Maybe s])
+  -- sinterstore, sunionstore, sdiffstore :: (Key k) => a -> k -> [k] -> IO (Bool)
+  -- smembers :: (Key k, Serializable s) => a -> k -> IO (Maybe [Maybe s])
+  -- srandmember :: (Key k, Serializable s) => a -> k -> IO (Maybe s)
+  -- 
+  -- zadd :: (Key k, Serializable s) => a -> k -> Int -> s -> IO (Bool)
+  -- zrem :: (Key k, Serializable s) => a -> k -> s -> IO (Bool)
+  -- zrange, zrevrange, zrangebyscore :: (Key k, Serializable s) => a -> k -> Int -> Int -> IO (Maybe [Maybe s])
+  -- zcard :: (Key k) => a -> k -> IO (Maybe Int)
+  -- zscore :: (Key k, Serializable s) => a -> k -> s -> IO (Maybe Int)
+  
+  select :: a -> Int -> IO (Bool)
+  move :: (Key k) => a -> k -> Int -> IO (Bool)
+  flushdb, flushall :: a -> IO (Bool)
+  
+  save, bgsave, shutdown :: a -> IO (Bool)
+  lastsave :: a -> IO (Maybe Int)
+  
+  pong :: a -> IO (Maybe String)
+  -- info :: a -> IO (Maybe [String])
+  -- monitor ::
+  -- slaveoff ::
+  
+instance Redis Server where
+  get = S.get
+  set = S.set
+  setnx = S.setnx
+  getset = S.getset
+  mget = S.mget
+  incr = S.incr
+  decr = S.incr
+  incrby = S.incrby
+  decrby = S.decrby
+  exists = S.exists
+  del = S.del
+  rtype = S.rtype
+
+  keys = K.keys
+  randomkey = K.randomkey
+  rename = K.rename
+  renamenx = K.renamenx
+  dbsize = K.dbsize
+  expire = K.expire
+  ttl = K.ttl
+
+  lrange = L.lrange
+  lpush = L.lpush
+  rpush = L.rpush
+  llen = L.llen
+  ltrim = L.ltrim
+  lindex = L.lindex
+  lset = L.lset
+  lrem = L.lrem
+  lpop = L.lpop
+  rpop = L.rpop
+  
+  -- sadd = SS.sadd
+  -- srem = SS.srem
+  -- spop = SS.spop
+  -- smove = SS.smove
+  -- scard = SS.scard
+  -- sismember = SS.sismember
+  -- sinter = SS.sinter
+  -- sunion = SS.sunion
+  -- sdiff = SS.sdiff
+  -- sinterstore = SS.sinterstore
+  -- sunionstore = SS.sunionstore
+  -- sdiffstore = SS.sdiffstore
+  -- smembers = SS.smembers
+  -- srandmember = SS.srandmember
+  
+  -- zadd = Z.zadd
+  -- zrem = Z.zrem
+  -- zrange = Z.zrange
+  -- zrevrange = Z.zrevrange
+  -- zrangebyscore = Z.zrangebyscore
+  -- zcard = Z.zcard
+  -- zscore = Z.zscore
+  
+  select = DBM.select
+  move = DBM.move
+  flushdb = DBM.flushdb
+  flushall = DBM.flushall
+
+  save = P.save
+  bgsave = P.bgsave
+  shutdown = P.shutdown
+  lastsave = P.lastsave
+  
+  pong = Misc.pong
+  -- info :: a -> IO (Maybe [String])
+  -- monitor ::
+  -- slaveoff ::
+

Database/Redis/DBM.hs

+module Database.Redis.DBM where
+
+import Database.Redis.Protocol
+import Database.Redis.Key
+import Database.Redis.Serializable
+
+select :: Server -> Int -> IO (Bool)
+select (Server handle) index = do
+  hPutCommand handle ["SELECT", show index]
+  val <- readSingleLineReply handle
+  case val of
+    Just "OK" -> return True
+    _ -> return False
+
+move :: (Key k) => Server -> k -> Int -> IO (Bool)
+move (Server handle) key index = do
+  hPutCommand handle ["MOVE", toKey key, show index]
+  intReplyAsBool handle
+
+flushdb :: Server -> IO (Bool)  
+flushdb = doManagementCommand "FLUSHDB"
+
+flushall :: Server -> IO (Bool)
+flushall = doManagementCommand "FLUSHALL"

Database/Redis/Key.hs

+-- Redis interface.
+-- Copyright (C) 2005 Evan Martin <martine@danga.com>
+
+module Database.Redis.Key
+  (
+      Key
+    , hash
+    , toKey
+  ) where
+
+import Data.List(foldl')
+
+-- A Redis key must be hashable (so it can be deterministically distributed
+-- across multiple servers) and convertable to a string (as that's what
+-- Redis uses).
+
+class Key a where
+  hash     :: a -> Int
+  toKey    :: a -> String
+
+-- I really just want to make String an instance of Key,
+-- but this is the best I can figure out.
+class KeyElem a where
+  num :: a -> Int
+  chr :: a -> Char
+instance KeyElem Char where
+  num = fromEnum
+  chr = id
+instance (KeyElem a) => Key [a] where
+  -- glib's string hash: fast and good for short strings
+  hash  = foldl' (\h i -> 31*h + i) 0 . map num
+  toKey = map chr
+
+-- vim: set ts=2 sw=2 et :

Database/Redis/Keys.hs

+module Database.Redis.Keys where
+  
+import Database.Redis.Protocol
+import Database.Redis.Key
+import Database.Redis.Serializable
+
+keys :: Server -> String -> IO (Maybe [String])
+keys (Server handle) pattern =  do
+  hPutCommand handle ["KEYS", pattern]
+  val <- readBulkReply handle
+  case val of 
+    Nothing -> return Nothing
+    Just val -> return $ Just (words val)
+
+randomkey :: Server -> IO (Maybe String)
+randomkey (Server handle) = do
+  hPutCommand handle ["RANDOMKEY"]
+  readSingleLineReply handle
+
+rename :: (Key k) => Server -> k -> k -> IO (Bool)
+rename (Server handle) oldkey newkey = do
+  hPutCommand handle ["RENAME", toKey oldkey, toKey newkey]
+  val <- readSingleLineReply handle
+  case val of
+    Just "OK" -> return True
+    _ -> return False
+
+renamenx :: (Key k) => Server -> k -> k -> IO (Bool)
+renamenx (Server handle) oldkey newkey = do
+  hPutCommand handle ["RENAMENX", toKey oldkey, toKey newkey]
+  intReplyAsBool handle
+  
+dbsize :: Server -> IO (Maybe Int)
+dbsize (Server handle) = do
+  hPutCommand handle ["DBSIZE"]
+  readIntegerReply handle
+
+expire :: (Key k) => Server -> k -> Int -> IO (Bool)
+expire (Server handle) key seconds = do
+  hPutCommand handle ["EXPIRE", toKey key, show seconds]
+  intReplyAsBool handle
+
+ttl :: (Key k) => Server -> k -> IO (Maybe Int)
+ttl (Server handle) key = do
+  hPutCommand handle ["TTL", toKey key]
+  readIntegerReply handle

Database/Redis/Lists.hs

+module Database.Redis.Lists where
+
+import Database.Redis.Protocol
+import Database.Redis.Key
+import Database.Redis.Serializable
+import System.IO
+
+lpush :: (Key k, Serializable s) => Server -> k -> s -> IO (Bool)
+lpush = doBulkCommand "LPUSH"
+
+rpush :: (Key k, Serializable s) => Server -> k -> s -> IO (Bool)
+rpush = doBulkCommand "RPUSH"
+
+lrange :: (Key k, Serializable s) => Server -> k -> Int -> Int -> IO (Maybe [Maybe s])
+lrange (Server handle) key start end = do
+  hPutCommand handle ["LRANGE", toKey key, show start, show end]
+  getMultiBulkReply handle
+
+llen :: (Key k) => Server -> k -> IO (Maybe Int)  
+llen (Server handle) key =  do
+  hPutCommand handle ["LLEN", toKey key]
+  readIntegerReply handle
+
+ltrim :: (Key k) => Server -> k -> Int -> Int -> IO (Bool)  
+ltrim (Server handle) key start end = do
+  hPutCommand handle ["LTRIM", toKey key, show start, show end]
+  val <- readSingleLineReply handle
+  case val of
+    Just "OK" -> return True
+    _ -> return False
+
+lindex :: (Key k, Serializable s) => Server -> k -> Int -> IO (Maybe s)
+lindex (Server handle) key index = do
+  hPutCommand handle ["LINDEX", toKey key, show index]
+  getBulkReply handle
+
+lset :: (Key k, Serializable s) => Server -> k -> Int -> s -> IO (Bool)  
+lset (Server handle) key index value = do
+  let valString = toString value
+  let bytes = length valString
+  hPutCommand handle ["LSET", toKey key, show index, show bytes]
+  hPutNetLn handle valString
+  hFlush handle
+  val <- readSingleLineReply handle
+  case val of
+    Just "OK" -> return True
+    _ -> return False
+
+lrem :: (Key k, Serializable s) => Server -> k -> Int -> s -> IO (Maybe Int)
+lrem (Server handle) key index value = do
+  let valString = toString value
+  let bytes = length valString
+  hPutCommand handle ["LREM", toKey key, show index, show bytes]
+  hPutNetLn handle valString
+  hFlush handle
+  readIntegerReply handle
+
+lpop :: (Key k, Serializable s) => Server -> k -> IO (Maybe s)  
+lpop (Server handle) key = do
+  hPutCommand handle ["LPOP", toKey key]
+  getBulkReply handle
+
+rpop :: (Key k, Serializable s) => Server -> k -> IO (Maybe s)
+rpop (Server handle) key = do
+  hPutCommand handle ["RPOP", toKey key]
+  getBulkReply handle

Database/Redis/Misc.hs

+module Database.Redis.Misc where
+
+import Database.Redis.Protocol
+import Database.Redis.Key
+import Database.Redis.Serializable
+
+pong :: Server -> IO (Maybe String)  
+pong (Server handle) = do
+  hPutCommand handle ["PING"]
+  readSingleLineReply handle

Database/Redis/Persistence.hs

+module Database.Redis.Persistence where
+
+import Database.Redis.Protocol
+import Database.Redis.Key
+import Database.Redis.Serializable
+
+save :: Server -> IO (Bool)
+save = doManagementCommand "SAVE"
+
+bgsave :: Server -> IO (Bool)
+bgsave = doManagementCommand "BGSAVE"
+
+shutdown :: Server -> IO (Bool)
+shutdown =  doManagementCommand "SHUTDOWN" 
+
+lastsave :: Server -> IO (Maybe Int)
+lastsave (Server handle) = do
+  hPutCommand handle ["LASTSAVE"]
+  readIntegerReply handle

Database/Redis/Protocol.hs

+module Database.Redis.Protocol where
+
+import qualified Network
+import Database.Redis.Key
+import Database.Redis.Serializable
+import System.IO
+
+newtype Server = Server { sHandle :: Handle }
+
+-- | Gather results from action until condition is true.
+ioUntil :: (a -> Bool) -> IO a -> IO [a]
+ioUntil stop io = do
+  val <- io
+  if stop val then return []
+              else do more <- ioUntil stop io
+                      return (val:more)
+
+-- | Put out a line with \r\n terminator.
+hPutNetLn :: Handle -> String -> IO ()
+hPutNetLn h str = hPutStr h (str ++ "\r\n")
+
+-- | Get a line, stripping \r\n terminator.
+hGetNetLn :: Handle -> IO [Char]
+hGetNetLn h = do
+  str <- ioUntil (== '\r') (hGetChar h)
+  hGetChar h   -- read following newline
+  return str
+
+-- | Put out a command (words with terminator) and flush.
+hPutCommand :: Handle -> [String] -> IO ()
+hPutCommand h strs = hPutNetLn h (unwords strs) >> hFlush h
+
+-- connect :: String -> Network.Socket.PortNumber -> IO Server
+connect :: Network.HostName -> Network.PortNumber -> IO Server
+connect host port = do
+  handle <- Network.connectTo host (Network.PortNumber port)
+  return (Server handle)
+
+disconnect :: Server -> IO ()
+disconnect = hClose . sHandle
+
+getOneValue :: Handle -> IO (Maybe String)
+getOneValue handle = do
+  s <- hGetNetLn handle
+  case words s of
+    ["VALUE", _, _, sbytes] -> do
+      let count = read sbytes
+      val <- sequence $ take count (repeat $ hGetChar handle)
+      return $ Just val
+    _ -> return Nothing
+
+--Redis specific commands: 
+sendBulkCommand :: (Key k, Serializable s) => String -> Handle -> k -> s -> IO ()
+sendBulkCommand action handle key val = do
+  let valString = toString val
+  let bytes = length valString
+  hPutCommand handle [action, toKey key, show bytes]
+  hPutNetLn handle valString
+  hFlush handle
+  return ()
+
+readIntegerReply :: Handle -> IO (Maybe Int)
+readIntegerReply handle = do
+  i <- hGetNetLn handle
+  case i of
+    (':':rest) -> return $ Just (read rest :: Int)
+    _ -> return Nothing
+
+readSingleLineReply :: Handle -> IO (Maybe String)
+readSingleLineReply handle = do
+  s <- hGetNetLn handle
+  case s of
+    ('+':rest) -> return $ Just rest
+    _ -> return Nothing
+  
+readBulkReply :: Handle -> IO (Maybe String)
+readBulkReply handle = do
+  s <- hGetNetLn handle
+  case s of
+    "$-1" -> return Nothing
+    ('$':nbytes) -> do
+      let count = read nbytes :: Int
+      val <- sequence $ take count (repeat $ hGetChar handle)
+      hGetNetLn handle -- read '\r\n'
+      return $ Just val
+    _ -> return Nothing
+
+readMultiBulkReply :: Handle -> IO (Maybe [Maybe String])
+readMultiBulkReply handle = do
+  s <- hGetNetLn handle
+  case s of
+    "*-1" -> return Nothing
+    ('*':nreplies) -> do
+      let count = read nreplies :: Int
+      val <- sequence $ take count (repeat $ readBulkReply handle)
+      return $ Just val
+    _ -> return Nothing
+
+doBulkCommand :: (Key k, Serializable s) => String -> Server -> k -> s -> IO Bool
+doBulkCommand action (Server handle) key value = do
+  sendBulkCommand action handle key value
+  val <- readSingleLineReply handle
+  case val of
+    (Just something) -> return True
+    Nothing -> return False
+    
+getBulkReply :: (Serializable s) => Handle -> IO (Maybe s)
+getBulkReply handle = do
+  val <- readBulkReply handle
+  case val of
+    Nothing  -> return Nothing
+    Just val -> return $ fromString val
+    
+getMultiBulkReply :: (Serializable s) => Handle -> IO (Maybe [Maybe s])
+getMultiBulkReply handle = do
+  values <- readMultiBulkReply handle
+  case values of
+    Nothing -> return Nothing
+    Just values -> return $ Just (map listToSerializable values)
+
+listToSerializable :: (Serializable s) => Maybe String -> Maybe s
+listToSerializable Nothing = Nothing
+listToSerializable (Just val) = fromString val
+
+incDec :: (Key k) => String -> Server -> k -> IO (Maybe Int)
+incDec cmd (Server handle) key = do
+  hPutCommand handle [cmd, toKey key]
+  readIntegerReply handle
+  
+incDecBy :: (Key k) => String -> Server -> k -> Int -> IO (Maybe Int)
+incDecBy cmd (Server handle) key delta = do
+  hPutCommand handle [cmd, toKey key, show delta]
+  readIntegerReply handle
+
+intReplyAsBool :: Handle -> IO (Bool)  
+intReplyAsBool handle = do
+  val <- readIntegerReply handle
+  case val of
+    Just 1  -> return True
+    _       -> return False
+
+doManagementCommand :: String -> Server -> IO Bool
+doManagementCommand action (Server handle) = do
+  hPutCommand handle [action]
+  val <- readSingleLineReply handle
+  case val of
+    Just "OK" -> return True
+    _ -> return False

Database/Redis/RSCC.hs

+module Database.Redis.RSCC where
+  
+import Database.Redis.Protocol
+import Database.Redis.Key
+import Database.Redis.Serializable

Database/Redis/Serializable.hs

+-- Redis interface.
+-- Copyright (C) 2005 Evan Martin <martine@danga.com>
+
+module Database.Redis.Serializable
+  (
+      Serializable
+    , toString
+    , fromString
+  ) where
+
+-- It'd be nice to use "show" for serialization, but when we
+-- serialize a String we want to serialize it without the quotes.
+
+-- TODO:
+--  - allow serializing bytes as Ptr
+--    to do this, add a "putToHandle", etc. method in Serializable
+--    where the default uses toString, but for Ptr uses socket stuff.
+
+--import Foreign.Marshal.Utils
+--import Foreign.Storable (Storable, sizeOf)
+
+class Serializable a where
+  toString    :: a -> String
+  fromString  :: String -> Maybe a
+
+  toStringL   :: [a] -> String
+  fromStringL :: String -> [a]
+
+  toStringL   = error "unimp"
+  fromStringL = error "unimp"
+
+instance Serializable Char where
+  -- people will rarely want to serialize a single char,
+  -- but we define them for completeness.
+  toString   x      = [x]
+  fromString (c:[]) = Just c
+  fromString _      = Nothing
+
+  -- the real use is for serializing strings.
+  toStringL   = id
+  fromStringL = id
+
+-- ...do I really need to copy everything instance of Show?
+instance Serializable Int where
+  toString   = show
+  fromString = Just . read
+
+instance (Serializable a) => Serializable [a] where
+  toString   = toStringL
+  fromString = Just . fromStringL
+
+-- vim: set ts=2 sw=2 et :

Database/Redis/Sets.hs

+module Database.Redis.Sets where
+  
+import Database.Redis.Protocol
+import Database.Redis.Key
+import Database.Redis.Serializable

Database/Redis/Strings.hs

+module Database.Redis.Strings where
+
+import Database.Redis.Protocol
+import Database.Redis.Key
+import Database.Redis.Serializable
+
+get :: (Key k, Serializable s) => Server -> k -> IO (Maybe s)
+get (Server handle) key = do
+  hPutCommand handle ["GET", toKey key]
+  getBulkReply handle
+
+set :: (Key k, Serializable s) => Server -> k -> s -> IO (Bool)
+set = doBulkCommand "SET"
+
+getset :: (Key k, Serializable s) => Server -> k -> s -> IO (Maybe s)
+getset (Server handle) key value = do
+  sendBulkCommand "GETSET" handle key value
+  getBulkReply handle
+
+mget :: (Key k, Serializable s) => Server -> [k] -> IO (Maybe [Maybe s])  
+mget (Server handle) keys = do
+  hPutCommand handle $ "MGET" : (map toKey keys)
+  getMultiBulkReply handle
+
+setnx :: (Key k, Serializable s) => Server -> k -> s -> IO (Bool)
+setnx (Server handle) key value = do
+  sendBulkCommand "SETNX" handle key value
+  intReplyAsBool handle
+
+incr :: (Key k) => Server -> k -> IO (Maybe Int)
+incr = incDec "INCR"
+
+decr :: (Key k) => Server -> k -> IO (Maybe Int)
+decr = incDec "DECR"
+
+incrby :: (Key k) => Server -> k -> Int -> IO (Maybe Int)
+incrby = incDecBy "INCRBY"
+
+decrby :: (Key k) => Server -> k -> Int -> IO (Maybe Int)
+decrby = incDecBy "DECRBY"
+
+exists :: (Key k) => Server -> k -> IO (Bool)
+exists (Server handle) key = do
+  hPutCommand handle ["EXISTS", toKey key]
+  intReplyAsBool handle
+
+del :: (Key k) => Server -> k -> IO (Bool)
+del (Server handle) key = do
+  hPutCommand handle ["DEL", toKey key]
+  intReplyAsBool handle
+
+rtype :: (Key k) => Server -> k -> IO (Maybe String)
+rtype (Server handle) key = do
+  hPutCommand handle ["TYPE", toKey key]
+  readSingleLineReply handle

Database/Redis/Zsets.hs

+module Database.Redis.Zsets where
+  
+import Database.Redis.Protocol
+import Database.Redis.Key
+import Database.Redis.Serializable
+module RedisTest where
+
+-- import Network.Redis(Redis)
+import qualified Database.Redis as R
+import Database.Redis.Protocol as Single
+import Database.Redis.Serializable(Serializable(..))
+  
+main = do
+  server <- Single.connect "127.0.0.1" 6379
+  pong <- R.pong server
+  putStrLn ("PING: " ++ show pong ++ ".")
+  
+  let val = "videla"
+  set <- R.set server "mykey" val
+  putStrLn ("SET: " ++ show set ++ ".")
+  
+  setnx <- R.setnx server "z" "y"
+  putStrLn ("SETNX: " ++ show setnx ++ ".")
+  
+  setnx' <- R.setnx server "y" "y"
+  putStrLn ("SETNX: " ++ show setnx' ++ ".")
+  
+  get <- R.get server "mykey"
+  case get of
+    Nothing -> putStrLn "get mykey got Nothing"
+    Just v ->  putStrLn ("GET: " ++ show (v::String) ++ ".")
+    
+  getset <- R.getset server "mykey" "videla"
+  case getset of
+    Nothing -> putStrLn "get mykey got Nothing"
+    Just v' ->  putStrLn ("GETSET: " ++ show (v'::String) ++ ".")
+    
+  get' <- R.get server "mykey"
+  case get' of
+    Nothing -> putStrLn "get mykey got Nothing"
+    Just v'' ->  putStrLn ("GET: " ++ show (v''::String) ++ ".")
+    
+  incr <- R.incr server "incrkey"
+  putStrLn ("INCR: " ++ show incr ++ ".")
+  
+  decr <- R.decr server "incrkey"
+  putStrLn ("DECR: " ++ show decr ++ ".")
+  
+  incrby <- R.incrby server "incrbykey" 5
+  putStrLn ("INCRBY: " ++ show incrby ++ ".")
+  
+  decrby <- R.decrby server "decrbykey" 5
+  putStrLn ("DECRBY: " ++ show decrby ++ ".")
+  
+  exists <- R.exists server "mykey"
+  putStrLn ("EXISTS: " ++ show exists ++ ".")
+  
+  del <- R.del server "mykey"
+  putStrLn ("DEL: " ++ show del ++ ".")
+  
+  exists' <- R.exists server "mykey"
+  putStrLn ("EXISTS: " ++ show exists' ++ ".")
+
+  del <- R.del server "mykey"
+  putStrLn ("DEL: " ++ show del ++ ".")
+    
+  let v1 = "en serio me lo decis?"
+  lp1 <- R.lpush server "lista" v1
+  putStrLn ("LPUSH: " ++ show lp1 ++ ".")
+  
+  let v2 = "como"
+  lp2 <- R.rpush server "lista" v2
+  putStrLn ("RPUSH: " ++ show lp2 ++ ".")
+  
+  mget <- R.mget server ["b", "e", "d"]
+  case mget of
+    Nothing -> putStrLn "mget got nothing"
+    Just mget' -> do
+      mapM_ (\h -> do putStrLn ("MGET: " ++ show (h::Maybe String) ++ ".")) mget'
+  
+  lrange <- R.lrange server "lista" 0 5
+  case lrange of
+    Nothing -> putStrLn "lrange got nothing"
+    Just lrange' -> do
+      mapM_ (\h -> do putStrLn ("LRANGE: " ++ show (h::Maybe String) ++ ".")) lrange'
+      
+  rtype <- R.rtype server "mykey"
+  putStrLn ("RTYPE: " ++ show rtype ++ ".")
+  
+  rtype' <- R.rtype server "lista"
+  putStrLn ("RTYPE: " ++ show rtype' ++ ".")
+  
+  rtype'' <- R.rtype server "a"
+  putStrLn ("RTYPE: " ++ show rtype'' ++ ".")
+  
+  keys <- R.keys server "*"
+  case keys of
+    Nothing -> putStrLn "keys got nothing"
+    Just val -> do
+      mapM_ (\v -> do putStrLn ("KEYS: " ++ show v ++ ".")) val
+  
+  randomkey <- R.randomkey server
+  putStrLn ("RANDOMKEY: " ++ show randomkey ++ ".")
+  
+  rename <- R.rename server "OaOa" "a"
+  putStrLn ("RENAME: " ++ show rename ++ ".")
+  
+  renamenx <- R.renamenx server "y" "OaOa"
+  putStrLn ("RENAMENX: " ++ show renamenx ++ ".")
+  
+  -- R.select server 1
+  -- R.flushdb server
+  -- R.flushall server
+  -- R.select server 0
+  
+  dbsize <- R.dbsize server
+  putStrLn ("DBSIZE: " ++ show dbsize ++ ".")
+  
+  expire <- R.expire server "b" 5
+  putStrLn ("EXPIRE: " ++ show expire ++ ".")
+  
+  ttl <- R.ttl server "y"
+  putStrLn ("TTL: " ++ show ttl ++ ".")
+  
+  llen <- R.llen server "lista"
+  putStrLn ("LLEN: " ++ show llen ++ ".")
+  
+  ltrim <- R.ltrim server "lista" 0 10
+  putStrLn ("LTRIM: " ++ show ltrim ++ ".")
+  
+  lindex <- R.lindex server "lista" 1
+  putStrLn ("LINDEX: " ++ show (lindex ::Maybe String) ++ ".")
+  
+  lset <- R.lset server "lista" 0 "nueva"
+  putStrLn ("LSET: " ++ show lset ++ ".")
+  
+  lrem <- R.lrem server "lista" 5 "en serio me lo decis?"
+  putStrLn ("LREM: " ++ show lrem ++ ".")
+  
+  lpop <- R.lpop server "lista"
+  case lpop of
+    Nothing -> putStrLn "lpop lista got Nothing"
+    Just v ->  putStrLn ("LPOP: " ++ show (v::String) ++ ".")
+  
+  rpop <- R.rpop server "lista"
+  case rpop of
+    Nothing -> putStrLn "rpop lista got Nothing"
+    Just v ->  putStrLn ("RPOP: " ++ show (v::String) ++ ".")
+      
+  Single.disconnect server