diff --git a/Database/Redis/Monad.hs b/Database/Redis/Monad.hs
--- a/Database/Redis/Monad.hs
+++ b/Database/Redis/Monad.hs
@@ -31,6 +31,7 @@
        R.Interval(..),
        R.IsInterval(..),
        R.SortOptions(..),
+       R.Aggregate(..),
        R.sortDefaults,
 
        R.fromRInline, R.fromRBulk, R.fromRMulti, R.fromRMultiBulk,
@@ -69,8 +70,13 @@
        zadd, zrem, zincrBy, zrange,
        zrevrange, zrangebyscore, zcount,
        zremrangebyscore, zcard, zscore,
-       zrank,
+       zrank, zrevrank, zremrangebyrank,
+       zunion, zinter,
 
+       -- ** Hashes
+       hset, hget, hdel, hexists, hlen,
+       hkeys, hvals, hgetall,
+
        -- ** Sorting
        sort, listRelated,
 
@@ -366,6 +372,54 @@
 zrank :: (WithRedis m, BS s1, BS s2) => s1 -> s2 -> m (R.Reply Int)
 zrank key member = do r <- getRedis
                       liftIO $ R.zrank r key member
+
+zrevrank :: (WithRedis m, BS s1, BS s2) => s1 -> s2 -> m (R.Reply Int)
+zrevrank key member = do r <- getRedis
+                         liftIO $ R.zrevrank r key member
+
+zremrangebyrank :: (WithRedis m, BS s) => s -> (Int, Int) -> m (R.Reply Int)
+zremrangebyrank key limit = do r <- getRedis
+                               liftIO $ R.zremrangebyrank r key limit
+
+zunion :: (WithRedis m, BS s1, BS s2) => s1 -> [s2] -> [Double] -> R.Aggregate -> m (R.Reply Int)
+zunion dst src weights aggregate = do r <- getRedis
+                                      liftIO $ R.zunion r dst src weights aggregate
+
+zinter :: (WithRedis m, BS s1, BS s2) => s1 -> [s2] -> [Double] -> R.Aggregate -> m (R.Reply Int)
+zinter dst src weights aggregate = do r <- getRedis
+                                      liftIO $ R.zinter r dst src weights aggregate
+
+hset :: (WithRedis m, BS s1, BS s2, BS s3) => s1 -> s2 -> s3 -> m (R.Reply Int)
+hset key field value = do r <- getRedis
+                          liftIO $ R.hset r key field value
+
+hget :: (WithRedis m, BS s1, BS s2, BS s3) => s1 -> s2 -> m (R.Reply s3)
+hget key field = do r <- getRedis
+                    liftIO $ R.hget r key field
+
+hdel :: (WithRedis m, BS s1, BS s2) => s1 -> s2 -> m (R.Reply Int)
+hdel key field = do r <- getRedis
+                    liftIO $ R.hdel r key field
+
+hexists :: (WithRedis m, BS s1, BS s2) => s1 -> s2 -> m (R.Reply Int)
+hexists key field = do r <- getRedis
+                       liftIO $ R.hexists r key field
+
+hlen :: (WithRedis m, BS s) => s -> m (R.Reply Int)
+hlen key = do r <- getRedis
+              liftIO $ R.hlen r key
+
+hkeys :: (WithRedis m, BS s1, BS s2) => s1 -> m (R.Reply s2)
+hkeys key = do r <- getRedis
+               liftIO $ R.hkeys r key
+
+hvals :: (WithRedis m, BS s1, BS s2) => s1 -> m (R.Reply s2)
+hvals key = do r <- getRedis
+               liftIO $ R.hvals r key
+
+hgetall :: (WithRedis m, BS s1, BS s2) => s1 -> m (R.Reply s2)
+hgetall key = do r <- getRedis
+                 liftIO $ R.hgetall r key
 
 sort :: (WithRedis m, BS s1, BS s2, BS s3) => s1 -> R.SortOptions s2 -> m (R.Reply s3)
 sort key opt = do r <- getRedis
diff --git a/Database/Redis/Redis.hs b/Database/Redis/Redis.hs
--- a/Database/Redis/Redis.hs
+++ b/Database/Redis/Redis.hs
@@ -31,6 +31,7 @@
        Interval(..),
        IsInterval(..),
        SortOptions(..),
+       Aggregate(..),
        sortDefaults,
        fromRInline, fromRBulk, fromRMulti, fromRMultiBulk,
        fromRInt, fromROk, noError, takeAll,
@@ -68,8 +69,13 @@
        zadd, zrem, zincrBy, zrange,
        zrevrange, zrangebyscore, zcount,
        zremrangebyscore, zcard, zscore,
-       zrank,
+       zrank, zrevrank, zremrangebyrank,
+       zunion, zinter,
 
+       -- ** Hashes
+       hset, hget, hdel, hexists, hlen,
+       hkeys, hvals, hgetall,
+
        -- ** Sorting
        sort, listRelated,
 
@@ -394,7 +400,7 @@
 
 -- | Return the type of the value stored at key in form of a string
 --
--- RInline with one of "none", "string", "list", "set", "zset" returned
+-- RInline with one of "none", "string", "list", "set", "zset", "hash" returned
 getType :: (BS s1, BS s2) =>
            Redis
         -> s1                   -- ^ target key
@@ -1126,6 +1132,161 @@
       -> s2
       -> IO (Reply Int)
 zrank r key member = sendCommand r (CMBulk ["ZRANK", toBS key, toBS member]) >> recv r
+
+-- | Returns sorted set element sequence number for reversed sort order
+--
+-- RInt returned
+zrevrank :: (BS s1, BS s2) =>
+            Redis
+         -> s1
+         -> s2
+         -> IO (Reply Int)
+zrevrank r key member = sendCommand r (CMBulk ["ZREVRANK", toBS key, toBS member]) >> recv r
+
+-- | Remove elements from the sorted set with rank lays within a given
+-- interval.
+--
+-- RInt returned - the number of elements removed
+zremrangebyrank :: (BS s) =>
+                   Redis
+                -> s
+                -> (Int, Int)
+                -> IO (Reply Int)
+zremrangebyrank r key (from, to) =
+    sendCommand r (CMBulk ["ZREMRANGEBYRANK", toBS key, toBS from, toBS to]) >> recv r
+
+data Aggregate = SUM | MIN | MAX
+                 deriving (Eq, Show)
+
+-- | Create a union of provided sorted sets and store it at /destination/ key
+--
+-- If /weights/ is not null then scores of sorted sets used with
+-- corresponding weights. If so lenght of /weights/ must be the same
+-- as length of /sources/.
+--
+-- /Aggregate/ is an option how to aggregate resulting scores.
+--
+-- RInt returned - the number of elements in the resulting set.
+zunion :: (BS s1, BS s2) =>
+          Redis
+       -> s1                    -- ^ destination key
+       -> [s2]                  -- ^ sources keys
+       -> [Double]              -- ^ weights
+       -> Aggregate             -- ^ aggregate
+       -> IO (Reply Int)
+zunion r dst src weights aggregate =
+    let src_s = toBS (length src) : map toBS src
+
+        weight_s | null weights = []
+                 | otherwise    = "WEIGHTS" : map toBS weights
+
+        aggr_s | aggregate == SUM = []
+               | otherwise        = ["AGGREGATE", toBS (show aggregate)]
+    in sendCommand r (CMBulk (("ZUNION" : toBS dst : src_s) ++ weight_s ++ aggr_s)) >> recv r
+
+-- | Create an intersectoin of provided sorted sets and store it at destination key
+--
+-- If /weights/ is not null then scores of sorted sets used with
+-- corresponding weights. If so lenght of /weights/ must be the same
+-- as length of /sources/.
+--
+-- Aggregate is an option how to aggregate resulting scores.
+--
+-- RInt returned - the number of elements in the resulting set.
+zinter :: (BS s1, BS s2) =>
+          Redis
+       -> s1                    -- ^ destination key
+       -> [s2]                  -- ^ sources keys
+       -> [Double]              -- ^ weights
+       -> Aggregate             -- ^ aggregate
+       -> IO (Reply Int)
+zinter r dst src weights aggregate =
+    let src_s = toBS (length src) : map toBS src
+
+        weight_s | null weights = []
+                 | otherwise    = "WEIGHTS" : map toBS weights
+
+        aggr_s | aggregate == SUM = []
+               | otherwise        = ["AGGREGATE", toBS (show aggregate)]
+    in sendCommand r (CMBulk (("ZINTER" : toBS dst : src_s) ++ weight_s ++ aggr_s)) >> recv r
+
+-- | Set the specified hash field to the specified value
+--
+-- (RInt 0 returned if field value was updated and (RInt 1) if new field created
+hset :: (BS s1, BS s2, BS s3) =>
+        Redis                   
+     -> s1                      -- ^ target key
+     -> s2                      -- ^ field name
+     -> s3                      -- ^ value
+     -> IO (Reply Int)
+hset r key field value = sendCommand r (CMBulk ["HSET", toBS key, toBS field, toBS value]) >> recv r
+
+-- | Return value associated with specified field from hash
+--
+-- RBulk returned
+hget :: (BS s1, BS s2, BS s3) =>
+        Redis
+     -> s1                      -- ^ key
+     -> s2                      -- ^ field name
+     -> IO (Reply s3)
+hget r key field = sendCommand r (CMBulk ["HGET", toBS key, toBS field]) >> recv r
+
+-- | Remove field from a hash
+--
+-- (RInt 1) returned if field was removed and (RInt 0) otherwise
+hdel :: (BS s1, BS s2) =>
+        Redis
+     -> s1                      -- ^ key
+     -> s2                      -- ^ field name
+     -> IO (Reply Int)
+hdel r key field = sendCommand r (CMBulk ["HDEL", toBS key, toBS field]) >> recv r
+
+-- | Test if hash contains the specified field
+--
+-- (RInt 1) returned if fiels exists and (RInt 0) otherwise
+hexists :: (BS s1, BS s2) =>
+           Redis
+        -> s1                   -- ^ key
+        -> s2                   -- ^ field name
+        -> IO (Reply Int)
+hexists r key field = sendCommand r (CMBulk ["HEXISTS", toBS key, toBS field]) >> recv r
+
+-- | Return the number of fields contained in the specified hash
+--
+-- RInt returned
+hlen :: (BS s) =>
+        Redis
+     -> s
+     -> IO (Reply Int)
+hlen r key = sendCommand r (CMBulk ["HLEN", toBS key]) >> recv r
+
+-- | Return all the field names the hash holding
+--
+-- RMulti field with RBulk returned
+hkeys :: (BS s1, BS s2) =>
+         Redis
+      -> s1
+      -> IO (Reply s2)
+hkeys r key = sendCommand r (CMBulk ["HKEYS", toBS key]) >> recv r
+
+-- | Return all the associated values the hash holding
+--
+-- RMulti field with RBulk returned
+hvals :: (BS s1, BS s2) =>
+         Redis
+      -> s1
+      -> IO (Reply s2)
+hvals r key = sendCommand r (CMBulk ["HVALS", toBS key]) >> recv r
+
+-- | Return all the field names and associated values the hash holding
+-- in form of /[field1, value1, field2, value2...]/
+--
+-- RMulti field with RBulk returned
+hgetall :: (BS s1, BS s2) =>
+           Redis
+        -> s1
+        -> IO (Reply s2)
+hgetall r key = sendCommand r (CMBulk ["HGETALL", toBS key]) >> recv r
 
 -- | Options data type for the 'sort' command
 data BS s => SortOptions s = SortOptions { desc       :: Bool,       -- ^ sort with descending order
diff --git a/redis.cabal b/redis.cabal
--- a/redis.cabal
+++ b/redis.cabal
@@ -1,5 +1,5 @@
 Name:                redis
-Version:             0.3.1
+Version:             0.4
 License:             MIT
 Maintainer:          Alexander Bogdanov <andorn@gmail.com>
 Author:              Alexander Bogdanov <andorn@gmail.com>
@@ -16,12 +16,11 @@
 	protocol. Most of the functions will work correctly with stable version
 	but not all.
 	.
-	Changes from v0.2:
-	.
-	- (!) A lot of data and function types changed. Now it is posible to get not only
-	  String result but also a ByteString and other.
+	Changes from v0.3:
 	.
-	- New protocol functions added: substr, zrank
+	- Updated for Redis v1.3.7
+	- new sorted sets commands added: zrevrank, zremrangebyrank, zunion, zinter
+	- new hash commands added: hset, hdel, hexists, hlen, hkeys, hvals, hgetall
 
 Stability:           beta
 Build-Type:          Simple
