diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,14 @@
+## 0.2
+
+* make concat more generic as to what the output is going to be, and at the same
+  time reduce the constraint on the input to just Access
+* make all byte array operation safer related to negative size. now replicate, zero, and alloc will returns
+  an empty byte array when asking for negative size
+* replace 'pack' in Data.ByteArray.Pack by 'fill', as to not conflict with 'Data.ByteArray.pack'.
+  Also swap the length and monadic action to be more naturally used
+* add a deprecated 'pack' that alias to 'fill' for now
+* loosen constraint of Data.ByteArray.Pack.putBytes from ByteArray to ByteArrayAccess
+
+## 0.1
+
+* Initial release
diff --git a/Data/ByteArray/Methods.hs b/Data/ByteArray/Methods.hs
--- a/Data/ByteArray/Methods.hs
+++ b/Data/ByteArray/Methods.hs
@@ -47,7 +47,9 @@
 
 -- | Allocate a new bytearray of specific size, and run the initializer on this memory
 alloc :: ByteArray ba => Int -> (Ptr p -> IO ()) -> IO ba
-alloc n f = snd `fmap` allocRet n f
+alloc n f
+    | n < 0     = alloc 0 f
+    | otherwise = snd `fmap` allocRet n f
 
 -- | Allocate a new bytearray of specific size, and run the initializer on this memory
 create :: ByteArray ba => Int -> (Ptr p -> IO ()) -> IO ba
@@ -137,7 +139,7 @@
 -- | drop the first @n byte of a bytearray
 drop :: ByteArray bs => Int -> bs -> bs
 drop n bs
-    | n  < 0    = bs
+    | n <= 0    = bs
     | nb == 0   = empty
     | otherwise = unsafeCreate nb $ \d -> withByteArray bs $ \s -> memCopy d (s `plusPtr` ofs) nb
   where
@@ -155,9 +157,18 @@
             | otherwise         = i
 
 -- | Concatenate bytearray into a larger bytearray
-concat :: ByteArray bs => [bs] -> bs
-concat = mconcat
+concat :: (ByteArrayAccess bin, ByteArray bout) => [bin] -> bout
+concat l = unsafeCreate retLen (loopCopy l)
+  where
+    retLen = sum $ map length l
 
+    loopCopy []     _   = return ()
+    loopCopy (x:xs) dst = do
+        withByteArray x $ \src -> memCopy dst src chunkLen
+        loopCopy xs (dst `plusPtr` chunkLen)
+      where
+        !chunkLen = length x
+
 -- | append one bytearray to the other
 append :: ByteArray bs => bs -> bs -> bs
 append = mappend
@@ -186,13 +197,17 @@
 -- | Create a bytearray of a specific size containing a repeated byte value
 replicate :: ByteArray ba => Int -> Word8 -> ba
 replicate 0 _ = empty
-replicate n b = unsafeCreate n $ \ptr -> memSet ptr b n
+replicate n b
+    | n < 0     = empty
+    | otherwise = unsafeCreate n $ \ptr -> memSet ptr b n
 {-# NOINLINE replicate #-}
 
 -- | Create a bytearray of a specific size initialized to 0
 zero :: ByteArray ba => Int -> ba
 zero 0 = empty
-zero n = unsafeCreate n $ \ptr -> memSet ptr 0 n
+zero n
+    | n < 0     = empty
+    | otherwise = unsafeCreate n $ \ptr -> memSet ptr 0 n
 {-# NOINLINE zero #-}
 
 -- | Check if two bytearray are equals
diff --git a/Data/ByteArray/Pack.hs b/Data/ByteArray/Pack.hs
--- a/Data/ByteArray/Pack.hs
+++ b/Data/ByteArray/Pack.hs
@@ -19,6 +19,7 @@
 module Data.ByteArray.Pack
     ( Packer
     , Result(..)
+    , fill
     , pack
       -- * Operations
       -- ** put
@@ -41,12 +42,12 @@
 import           Data.Memory.Internal.Compat
 import           Data.Memory.PtrMethods
 import           Data.ByteArray.Pack.Internal
-import           Data.ByteArray (ByteArray, MemView(..))
+import           Data.ByteArray (ByteArray, ByteArrayAccess, MemView(..))
 import qualified Data.ByteArray as B
 
--- | pack the given packer into the given bytestring
-pack :: ByteArray byteArray => Packer a -> Int -> Either String byteArray
-pack packing len = unsafeDoIO $ do
+-- | fill a given sized buffer with the result of the Packer action
+fill :: ByteArray byteArray => Int -> Packer a -> Either String byteArray
+fill len packing = unsafeDoIO $ do
     (val, out) <- B.allocRet len $ \ptr -> runPacker_ packing (MemView ptr len)
     case val of 
         PackerMore _ (MemView _ r)
@@ -54,6 +55,11 @@
             | otherwise -> return $ Left ("remaining unpacked bytes " ++ show r ++ " at the end of buffer")
         PackerFail err  -> return $ Left err
 
+-- | pack the given packer into the given bytestring
+pack :: ByteArray byteArray => Packer a -> Int -> Either String byteArray
+pack packing len = fill len packing
+{-# DEPRECATED pack "use fill instead" #-}
+
 fillUpWithWord8' :: Word8 -> Packer ()
 fillUpWithWord8' w = Packer $ \(MemView ptr size) -> do
     memSet ptr w size
@@ -66,7 +72,7 @@
 -- | put a Byte Array from the current position in the stream
 --
 -- If the ByteArray is null, then do nothing
-putBytes :: ByteArray ba => ba -> Packer ()
+putBytes :: ByteArrayAccess ba => ba -> Packer ()
 putBytes bs
     | neededLength == 0 = return ()
     | otherwise         =
diff --git a/memory.cabal b/memory.cabal
--- a/memory.cabal
+++ b/memory.cabal
@@ -1,5 +1,5 @@
 Name:                memory
-Version:             0.1
+Version:             0.2
 Synopsis:            memory and related abtraction stuff
 Description:
     Chunk of memory, polymorphic byte array management and manipulation
@@ -19,7 +19,7 @@
 Homepage:            https://github.com/vincenthz/hs-memory
 Bug-Reports:         https://github.com/vincenthz/hs-memory/issues
 Cabal-Version:       >=1.10
-extra-source-files:  README.md
+extra-doc-files:     README.md CHANGELOG.md
 
 source-repository head
   type: git
diff --git a/tests/Tests.hs b/tests/Tests.hs
--- a/tests/Tests.hs
+++ b/tests/Tests.hs
@@ -133,5 +133,5 @@
         , testProperty "concat l" $ \(SmallList l) ->
             let chunks   = map (witnessID . B.pack . unWords8) l
                 expected = concatMap unWords8 l
-             in B.pack expected == B.concat chunks
+             in B.pack expected == witnessID (B.concat chunks)
         ]
