diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,11 @@
+## 0.4
+
+* add Ord instances for SipHash and FnvHash (Nicolas Di Prima)
+
+## 0.3
+
+* fix missing modules from tests on sdist
+
 ## 0.2
 
 * make concat more generic as to what the output is going to be, and at the same
diff --git a/Data/ByteArray.hs b/Data/ByteArray.hs
--- a/Data/ByteArray.hs
+++ b/Data/ByteArray.hs
@@ -21,6 +21,7 @@
     , module Data.ByteArray.Bytes
     , module Data.ByteArray.ScrubbedBytes
     , module Data.ByteArray.MemView
+    , module Data.ByteArray.View
     -- * ByteArray methods
     , module Data.ByteArray.Methods
     ) where
@@ -30,3 +31,4 @@
 import           Data.ByteArray.ScrubbedBytes (ScrubbedBytes)
 import           Data.ByteArray.Bytes         (Bytes)
 import           Data.ByteArray.MemView       (MemView(..))
+import           Data.ByteArray.View          (View, view, takeView, dropView)
diff --git a/Data/ByteArray/Bytes.hs b/Data/ByteArray/Bytes.hs
--- a/Data/ByteArray/Bytes.hs
+++ b/Data/ByteArray/Bytes.hs
@@ -162,10 +162,10 @@
         loop (idx +# chunkLenM1 -# 1#) paramAcc
       where loop i acc
                 | booleanPrim (i ==# idx) = do
-                    c <- rChar idx
+                    c <- rChar i
                     return (c : acc)
                 | otherwise = do
-                    c <- rChar idx
+                    c <- rChar i
                     loop (i -# 1#) (c : acc)
 
     rChar :: Int# -> IO Char
diff --git a/Data/ByteArray/View.hs b/Data/ByteArray/View.hs
new file mode 100644
--- /dev/null
+++ b/Data/ByteArray/View.hs
@@ -0,0 +1,128 @@
+-- |
+-- Module      : Data.ByteArray.View
+-- License     : BSD-style
+-- Maintainer  : Nicolas DI PRIMA <nicolas@di-prima.fr>
+-- Stability   : stable
+-- Portability : Good
+--
+-- a View on a given ByteArrayAccess
+--
+
+module Data.ByteArray.View
+    ( View
+    , view
+    , takeView
+    , dropView
+    ) where
+
+import Data.ByteArray.Methods
+import Data.ByteArray.Types
+import Data.Memory.PtrMethods
+import Data.Memory.Internal.Compat
+import Foreign.Ptr (plusPtr)
+
+import Prelude hiding (length, take, drop)
+
+-- | a view on a given bytes
+--
+-- Equality test in constant time
+data View bytes = View
+    { viewOffset :: !Int
+    , viewSize   :: !Int
+    , unView     :: !bytes
+    }
+
+instance ByteArrayAccess bytes => Eq (View bytes) where
+    (==) = constEq
+
+instance ByteArrayAccess bytes => Ord (View bytes) where
+    compare v1 v2 = unsafeDoIO $
+        withByteArray v1 $ \ptr1 ->
+        withByteArray v2 $ \ptr2 -> do
+            ret <- memCompare ptr1 ptr2 (min (viewSize v1) (viewSize v2))
+            return $ case ret of
+                EQ | length v1 >  length v2 -> GT
+                   | length v1 <  length v2 -> LT
+                   | length v1 == length v2 -> EQ
+                _                           -> ret
+
+instance ByteArrayAccess bytes => Show (View bytes) where
+    showsPrec p v r = showsPrec p (viewUnpackChars v []) r
+
+instance ByteArrayAccess bytes => ByteArrayAccess (View bytes) where
+    length = viewSize
+    withByteArray v f = withByteArray (unView v) $ \ptr -> f (ptr `plusPtr` (viewOffset v))
+
+viewUnpackChars :: ByteArrayAccess bytes
+                => View bytes
+                -> String
+                -> String
+viewUnpackChars v xs = chunkLoop 0
+  where
+    len = length v
+
+    chunkLoop :: Int -> [Char]
+    chunkLoop idx
+        | len == idx = []
+        | (len - idx) > 63 =
+            bytesLoop idx (idx + 64) (chunkLoop (idx + 64))
+        | otherwise =
+            bytesLoop idx (len - idx) xs
+
+    bytesLoop :: Int -> Int -> [Char] -> [Char]
+    bytesLoop idx chunkLenM1 paramAcc =
+        loop (idx + chunkLenM1 - 1) paramAcc
+      where
+        loop i acc
+            | i == idx  = (rChar i : acc)
+            | otherwise = loop (i - 1) (rChar i : acc)
+
+    rChar :: Int -> Char
+    rChar idx = toEnum $ fromIntegral $ index v idx
+
+-- | create a view on a given bytearray
+--
+-- This function update the offset and the size in order to guarantee:
+--
+-- * offset >= 0
+-- * size >= 0
+-- * offset < length
+-- * size =< length - offset
+--
+view :: ByteArrayAccess bytes
+     => bytes -- ^ the byte array we put a view on
+     -> Int   -- ^ the offset to start the byte array on
+     -> Int   -- ^ the size of the view
+     -> View bytes
+view b offset'' size'' = View offset size b
+  where
+    -- make sure offset is not negative
+    offset' :: Int
+    offset' = max offset'' 0
+
+    -- make sure the offset is not out of bound
+    offset :: Int
+    offset = min offset' (length b - 1)
+
+    -- make sure length is not negative
+    size' :: Int
+    size' = max size'' 0
+
+    -- make sure the length is not out of the bound
+    size :: Int
+    size = min size' (length b - offset)
+
+-- | create a view from the given bytearray
+takeView :: ByteArrayAccess bytes
+         => bytes -- ^ byte aray
+         -> Int   -- ^ size of the view
+         -> View bytes
+takeView b size = view b 0 size
+
+-- | create a view from the given byte array
+-- starting after having dropped the fist n bytes
+dropView :: ByteArrayAccess bytes
+         => bytes -- ^ byte array
+         -> Int   -- ^ the number of bytes do dropped before creating the view
+         -> View bytes
+dropView b offset = view b offset (length b - offset)
diff --git a/Data/Memory/Hash/FNV.hs b/Data/Memory/Hash/FNV.hs
--- a/Data/Memory/Hash/FNV.hs
+++ b/Data/Memory/Hash/FNV.hs
@@ -34,11 +34,11 @@
 
 -- | FNV1(a) hash (32 bit variants)
 newtype FnvHash32 = FnvHash32 Word32
-    deriving (Show,Eq,NFData)
+    deriving (Show,Eq,Ord,NFData)
 
 -- | FNV1(a) hash (64 bit variants)
 newtype FnvHash64 = FnvHash64 Word64
-    deriving (Show,Eq,NFData)
+    deriving (Show,Eq,Ord,NFData)
 
 -- | compute FNV1 (32 bit variant) of a raw piece of memory
 fnv1 :: Ptr Word8 -> Int -> IO FnvHash32
diff --git a/Data/Memory/Hash/SipHash.hs b/Data/Memory/Hash/SipHash.hs
--- a/Data/Memory/Hash/SipHash.hs
+++ b/Data/Memory/Hash/SipHash.hs
@@ -29,7 +29,7 @@
 
 -- | Siphash tag value
 newtype SipHash = SipHash Word64
-    deriving (Show,Eq)
+    deriving (Show,Eq,Ord)
 
 data InternalState = InternalState {-# UNPACK #-} !Word64 {-# UNPACK #-} !Word64 {-# UNPACK #-} !Word64 {-# UNPACK #-} !Word64
 
diff --git a/Data/Memory/Internal/Compat.hs b/Data/Memory/Internal/Compat.hs
--- a/Data/Memory/Internal/Compat.hs
+++ b/Data/Memory/Internal/Compat.hs
@@ -66,7 +66,7 @@
     (w `shiftR` 8) .|. (w `shiftL` 8)
 #endif
 
-#if !(MIN_VERSION_base(4,4,0))
+#if !(MIN_VERSION_base(4,5,0))
 unsafeShiftL :: Bits a => a -> Int -> a
 unsafeShiftL = shiftL
 
diff --git a/memory.cabal b/memory.cabal
--- a/memory.cabal
+++ b/memory.cabal
@@ -1,5 +1,5 @@
 Name:                memory
-Version:             0.3
+Version:             0.4
 Synopsis:            memory and related abtraction stuff
 Description:
     Chunk of memory, polymorphic byte array management and manipulation
@@ -62,6 +62,7 @@
                      Data.ByteArray.ScrubbedBytes
                      Data.ByteArray.Methods
                      Data.ByteArray.MemView
+                     Data.ByteArray.View
   Build-depends:     base >= 4 && < 5
                    , ghc-prim
   -- FIXME armel or mispel is also little endian.
