diff --git a/Control/Monad/Primitive.hs b/Control/Monad/Primitive.hs
--- a/Control/Monad/Primitive.hs
+++ b/Control/Monad/Primitive.hs
@@ -14,11 +14,12 @@
 module Control.Monad.Primitive (
   PrimMonad(..), RealWorld, primitive_,
   primToPrim, primToIO, primToST,
-  unsafePrimToPrim, unsafePrimToIO, unsafePrimToST
+  unsafePrimToPrim, unsafePrimToIO, unsafePrimToST,
+  unsafeInlinePrim, unsafeInlineIO, unsafeInlineST
 ) where
 
 import GHC.Prim   ( State#, RealWorld )
-import GHC.Base   ( unsafeCoerce# )
+import GHC.Base   ( unsafeCoerce#, realWorld# )
 import GHC.IOBase ( IO(..) )
 import GHC.ST     ( ST(..) )
 
@@ -76,4 +77,16 @@
 -- | Convert any 'PrimMonad' to 'IO'. This operation is highly unsafe!
 unsafePrimToIO :: PrimMonad m => m a -> IO a
 unsafePrimToIO = unsafePrimToPrim
+
+unsafeInlinePrim :: PrimMonad m => m a -> a
+{-# INLINE unsafeInlinePrim #-}
+unsafeInlinePrim m = unsafeInlineIO (unsafePrimToIO m)
+
+unsafeInlineIO :: IO a -> a
+{-# INLINE unsafeInlineIO #-}
+unsafeInlineIO m = case internal m realWorld# of (# _, r #) -> r
+
+unsafeInlineST :: ST s a -> a
+{-# INLINE unsafeInlineST #-}
+unsafeInlineST = unsafeInlinePrim
 
diff --git a/Data/Primitive/Addr.hs b/Data/Primitive/Addr.hs
--- a/Data/Primitive/Addr.hs
+++ b/Data/Primitive/Addr.hs
@@ -2,7 +2,7 @@
 
 -- |
 -- Module      : Data.Primitive.Addr
--- Copyright   : (c) Roman Leshchinskiy 2009
+-- Copyright   : (c) Roman Leshchinskiy 2009-2010
 -- License     : BSD-style
 --
 -- Maintainer  : Roman Leshchinskiy <rl@cse.unsw.edu.au>
diff --git a/Data/Primitive/Array.hs b/Data/Primitive/Array.hs
--- a/Data/Primitive/Array.hs
+++ b/Data/Primitive/Array.hs
@@ -1,8 +1,8 @@
-{-# LANGUAGE MagicHash, UnboxedTuples #-}
+{-# LANGUAGE MagicHash, UnboxedTuples, DeriveDataTypeable #-}
 
 -- |
 -- Module      : Data.Primitive.Array
--- Copyright   : (c) Roman Leshchinskiy 2009
+-- Copyright   : (c) Roman Leshchinskiy 2009-2010
 -- License     : BSD-style
 --
 -- Maintainer  : Roman Leshchinskiy <rl@cse.unsw.edu.au>
@@ -23,11 +23,15 @@
 import GHC.Base  ( Int(..) )
 import GHC.Prim
 
+import Data.Typeable ( Typeable )
+import Data.Data ( Data(..), mkNorepType )
+
 -- | Boxed arrays
-data Array a = Array (Array# a)
+data Array a = Array (Array# a) deriving ( Typeable )
 
 -- | Mutable boxed arrays associated with a primitive state token.
 data MutableArray s a = MutableArray (MutableArray# s a)
+                                deriving ( Typeable )
 
 -- | Create a new mutable array of the specified size and initialise all
 -- elements with the given value.
@@ -101,4 +105,14 @@
 {-# INLINE sameMutableArray #-}
 sameMutableArray (MutableArray arr#) (MutableArray brr#)
   = sameMutableArray# arr# brr#
+
+instance Typeable a => Data (Array a) where
+  toConstr _ = error "toConstr"
+  gunfold _ _ = error "gunfold"
+  dataTypeOf _ = mkNorepType "Data.Primitive.Array.Array"
+
+instance (Typeable s, Typeable a) => Data (MutableArray s a) where
+  toConstr _ = error "toConstr"
+  gunfold _ _ = error "gunfold"
+  dataTypeOf _ = mkNorepType "Data.Primitive.Array.MutableArray"
 
diff --git a/Data/Primitive/ByteArray.hs b/Data/Primitive/ByteArray.hs
--- a/Data/Primitive/ByteArray.hs
+++ b/Data/Primitive/ByteArray.hs
@@ -1,8 +1,9 @@
-{-# LANGUAGE MagicHash, UnboxedTuples #-}
+{-# LANGUAGE MagicHash, UnboxedTuples, ForeignFunctionInterface,
+             UnliftedFFITypes, DeriveDataTypeable #-}
 
 -- |
 -- Module      : Data.Primitive.ByteArray
--- Copyright   : (c) Roman Leshchinskiy 2009
+-- Copyright   : (c) Roman Leshchinskiy 2009-2010
 -- License     : BSD-style
 --
 -- Maintainer  : Roman Leshchinskiy <rl@cse.unsw.edu.au>
@@ -12,26 +13,34 @@
 --
 
 module Data.Primitive.ByteArray (
-  ByteArray(..), MutableByteArray(..),
+  ByteArray(..), MutableByteArray(..), ByteArray#, MutableByteArray#,
 
   newByteArray, newPinnedByteArray, newAlignedPinnedByteArray,
   readByteArray, writeByteArray, indexByteArray,
   unsafeFreezeByteArray,
   sizeofByteArray, sizeofMutableByteArray, sameMutableByteArray,
-  byteArrayContents
+  byteArrayContents,
+
+  memcpyByteArray, memcpyByteArray', memmoveByteArray, memsetByteArray
 ) where
 
 import Control.Monad.Primitive
 import Data.Primitive.Types
 
+import Foreign.C.Types
+import Data.Word ( Word8 )
 import GHC.Base ( Int(..) )
 import GHC.Prim
 
+import Data.Typeable ( Typeable )
+import Data.Data ( Data(..), mkNorepType )
+
 -- | Byte arrays
-data ByteArray = ByteArray ByteArray#
+data ByteArray = ByteArray ByteArray# deriving ( Typeable )
 
 -- | Mutable byte arrays associated with a primitive state token
 data MutableByteArray s = MutableByteArray (MutableByteArray# s)
+                                        deriving( Typeable )
 
 -- | Create a new mutable byte array of the specified size.
 newByteArray :: PrimMonad m => Int -> m (MutableByteArray (PrimState m))
@@ -110,4 +119,75 @@
 {-# INLINE writeByteArray #-}
 writeByteArray (MutableByteArray arr#) (I# i#) x
   = primitive_ (writeByteArray# arr# i# x)
+
+memcpyByteArray
+  :: PrimMonad m => MutableByteArray (PrimState m) -> Int
+                 -> MutableByteArray (PrimState m) -> Int
+                 -> Int -> m ()
+{-# INLINE memcpyByteArray #-}
+memcpyByteArray (MutableByteArray dst#) doff
+                (MutableByteArray src#) soff sz
+  = unsafePrimToPrim
+  $ memcpy_mba dst# (fromIntegral doff) src# (fromIntegral soff)
+                    (fromIntegral sz)
+
+memcpyByteArray'
+  :: PrimMonad m => MutableByteArray (PrimState m) -> Int
+                 -> ByteArray -> Int
+                 -> Int -> m ()
+{-# INLINE memcpyByteArray' #-}
+memcpyByteArray' (MutableByteArray dst#) doff
+                 (ByteArray src#) soff sz
+  = unsafePrimToPrim
+  $ memcpy_ba dst# (fromIntegral doff) src# (fromIntegral soff)
+                 (fromIntegral sz)
+
+memmoveByteArray
+  :: PrimMonad m => MutableByteArray (PrimState m) -> Int
+                 -> MutableByteArray (PrimState m) -> Int
+                 -> Int -> m ()
+{-# INLINE memmoveByteArray #-}
+memmoveByteArray (MutableByteArray dst#) doff
+                 (MutableByteArray src#) soff sz
+  = unsafePrimToPrim
+  $ memmove_mba dst# (fromIntegral doff) src# (fromIntegral soff)
+                     (fromIntegral sz)
+
+memsetByteArray
+  :: PrimMonad m => MutableByteArray (PrimState m) -> Int -> Word8
+                 -> Int -> m ()
+{-# INLINE memsetByteArray #-}
+memsetByteArray (MutableByteArray dst#) doff c sz
+  = unsafePrimToPrim
+  $ memset_mba dst# (fromIntegral doff) (fromIntegral c) (fromIntegral sz)
+
+
+
+foreign import ccall unsafe "primitive-memops.h memcpy_off"
+  memcpy_mba :: MutableByteArray# s -> CInt
+             -> MutableByteArray# s -> CInt
+             -> CSize -> IO ()
+
+foreign import ccall unsafe "primitive-memops.h memcpy_off"
+  memcpy_ba :: MutableByteArray# s -> CInt
+            -> ByteArray# -> CInt
+            -> CSize -> IO ()
+
+foreign import ccall unsafe "primitive-memops.h memmove_off"
+  memmove_mba :: MutableByteArray# s -> CInt
+              -> MutableByteArray# s -> CInt
+              -> CSize -> IO ()
+
+foreign import ccall unsafe "primitive-memops.h memset_off"
+  memset_mba :: MutableByteArray# s -> CInt -> CInt -> CSize -> IO ()
+
+instance Data ByteArray where
+  toConstr _ = error "toConstr"
+  gunfold _ _ = error "gunfold"
+  dataTypeOf _ = mkNorepType "Data.Primitive.ByteArray.ByteArray"
+
+instance Typeable s => Data (MutableByteArray s) where
+  toConstr _ = error "toConstr"
+  gunfold _ _ = error "gunfold"
+  dataTypeOf _ = mkNorepType "Data.Primitive.ByteArray.MutableByteArray"
 
diff --git a/Data/Primitive/Types.hs b/Data/Primitive/Types.hs
--- a/Data/Primitive/Types.hs
+++ b/Data/Primitive/Types.hs
@@ -1,8 +1,8 @@
-{-# LANGUAGE UnboxedTuples, MagicHash, CPP #-}
+{-# LANGUAGE UnboxedTuples, MagicHash, CPP, DeriveDataTypeable #-}
 
 -- |
 -- Module      : Data.Primitive.Types
--- Copyright   : (c) Roman Leshchinskiy 2009
+-- Copyright   : (c) Roman Leshchinskiy 2009-2010
 -- License     : BSD-style
 --
 -- Maintainer  : Roman Leshchinskiy <rl@cse.unsw.edu.au>
@@ -35,8 +35,11 @@
 
 import GHC.Prim
 
+import Data.Typeable ( Typeable )
+import Data.Data ( Data(..), mkNorepType )
+
 -- | A machine address
-data Addr = Addr Addr#
+data Addr = Addr Addr# deriving ( Typeable )
 
 instance Eq Addr where
   Addr a# == Addr b# = eqAddr# a# b#
@@ -47,6 +50,12 @@
   Addr a# >= Addr b# = geAddr# a# b#
   Addr a# < Addr b# = ltAddr# a# b#
   Addr a# <= Addr b# = leAddr# a# b#
+
+instance Data Addr where
+  toConstr _ = error "toConstr"
+  gunfold _ _ = error "gunfold"
+  dataTypeOf _ = mkNorepType "Data.Primitive.Types.Addr"
+
 
 -- | Class of types supporting primitive array operations
 class Prim a where
diff --git a/cbits/primitive-memops.c b/cbits/primitive-memops.c
new file mode 100644
--- /dev/null
+++ b/cbits/primitive-memops.c
@@ -0,0 +1,17 @@
+#include <string.h>
+
+void memcpy_off( void *dst, int doff, void *src, int soff, size_t len )
+{
+  memcpy( (char *)dst + doff, (char *)src + soff, len );
+}
+
+void memmove_off( void *dst, int doff, void *src, int soff, size_t len )
+{
+  memmove( (char *)dst + doff, (char *)src + soff, len );
+}
+
+void memset_off( void *dst, int doff, int c, size_t len )
+{
+  memset( (char *)dst + doff, c, len );
+}
+
diff --git a/cbits/primitive-memops.h b/cbits/primitive-memops.h
new file mode 100644
--- /dev/null
+++ b/cbits/primitive-memops.h
@@ -0,0 +1,11 @@
+#ifndef haskell_primitive_memops_h
+#define haskell_primitive_memops_h
+
+#include <stdlib.h>
+
+void memcpy_off( void *dst, int doff, void *src, int soff, size_t len );
+void memmove_off( void *dst, int doff, void *src, int soff, size_t len );
+void memset_off( void *dst, int doff, int c, size_t len );
+
+#endif
+
diff --git a/primitive.cabal b/primitive.cabal
--- a/primitive.cabal
+++ b/primitive.cabal
@@ -1,10 +1,10 @@
 Name:           primitive
-Version:        0.2.1
+Version:        0.3
 License:        BSD3
 License-File:   LICENSE
 Author:         Roman Leshchinskiy <rl@cse.unsw.edu.au>
 Maintainer:     Roman Leshchinskiy <rl@cse.unsw.edu.au>
-Copyright:      (c) Roman Leshchinskiy 2009-10
+Copyright:      (c) Roman Leshchinskiy 2009-2010
 Homepage:       http://code.haskell.org/primitive
 Category:       Data
 Synopsis:       Wrappers for primitive operations
@@ -27,5 +27,12 @@
         Data.Primitive.ByteArray
         Data.Primitive.Addr
 
-  Build-Depends: base >= 2 && < 5, ghc-prim
+  Build-Depends: base >= 4 && < 5, ghc-prim
+
+  Ghc-Options: -O2
+
+  Include-Dirs: cbits
+  Install-Includes: primitive-memops.h
+  includes: primitive-memops.h
+  c-sources: cbits/primitive-memops.c
 
