diff --git a/prim-array.cabal b/prim-array.cabal
--- a/prim-array.cabal
+++ b/prim-array.cabal
@@ -1,5 +1,5 @@
 name: prim-array
-version: 0.2
+version: 0.2.1
 synopsis: Primitive byte array with type variable
 homepage: https://github.com/andrewthad/prim-array#readme
 license: BSD3
diff --git a/src/Data/Primitive/PrimArray.hs b/src/Data/Primitive/PrimArray.hs
--- a/src/Data/Primitive/PrimArray.hs
+++ b/src/Data/Primitive/PrimArray.hs
@@ -3,6 +3,7 @@
 {-# LANGUAGE UnboxedTuples #-}
 {-# LANGUAGE RankNTypes #-}
 {-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeFamilies #-}
 
 {-# OPTIONS_GHC -Wall #-}
 
@@ -12,6 +13,8 @@
   , MutablePrimArray(..)
     -- * Allocation
   , newPrimArray
+  , emptyPrimArray
+  , singletonPrimArray
     -- * Element Access
   , readPrimArray
   , writePrimArray
@@ -22,17 +25,24 @@
     -- * Block Operations
   , copyPrimArray
   , copyMutablePrimArray
+  , copyPrimArrayToPtr
+  , copyPtrToMutablePrimArray
+  , copyPtrToPrimArray
   , setPrimArray
     -- * Information
   , sameMutablePrimArray
   , getSizeofMutablePrimArray
+  , sizeofPrimArray
   ) where
 
 import GHC.Prim
-import GHC.Exts (isTrue#)
+import GHC.Exts (isTrue#,IsList(..))
 import GHC.Int
+import GHC.Ptr
 import Data.Primitive
 import Control.Monad.Primitive
+import Control.Monad.ST
+import qualified Data.List as L
 import qualified Data.Primitive.Types as PT
 
 -- | Primitive arrays
@@ -41,6 +51,70 @@
 -- | Mutable primitive arrays associated with a primitive state token
 data MutablePrimArray s a = MutablePrimArray (MutableByteArray# s)
 
+instance (Eq a, Prim a) => Eq (PrimArray a) where
+  a1 == a2 = sizeofPrimArray a1 == sizeofPrimArray a2 && loop (sizeofPrimArray a1 - 1)
+    where 
+    loop !i | i < 0 = True
+            | otherwise = indexPrimArray a1 i == indexPrimArray a2 i && loop (i-1)
+
+instance Prim a => IsList (PrimArray a) where
+  type Item (PrimArray a) = a
+  fromList xs = primArrayFromList (L.length xs) xs
+  fromListN = primArrayFromList
+  toList = primArrayToList
+
+instance (Prim a, Show a) => Show (PrimArray a) where
+  showsPrec p = showsPrec p . primArrayToList
+
+primArrayFromList :: forall a. Prim a => Int -> [a] -> PrimArray a
+primArrayFromList len vs = runST run where
+  run :: forall s. ST s (PrimArray a)
+  run = do
+    arr <- newPrimArray len
+    let go :: [a] -> Int -> ST s ()
+        go !xs !ix = case xs of
+          [] -> return ()
+          a : as -> do
+            writePrimArray arr ix a
+            go as (ix + 1)
+    go vs 0
+    unsafeFreezePrimArray arr
+
+primArrayToList :: forall a. Prim a => PrimArray a -> [a]
+primArrayToList arr = go 0 where
+  !len = sizeofPrimArray arr
+  go :: Int -> [a]
+  go !ix = if ix < len
+    then indexPrimArray arr ix : go (ix + 1)
+    else []
+
+
+-- It is actually possible to write this without the Prim constraint
+-- on the type variable a. You just copy the byte arrays using
+-- more primitive operations.
+instance Prim a => Monoid (PrimArray a) where
+  mempty = emptyPrimArray
+  mappend a b = runST $ do
+    let szA = sizeofPrimArray a
+    let szB = sizeofPrimArray b
+    c <- newPrimArray (szA + szB)
+    copyPrimArray c 0 a 0 szA
+    copyPrimArray c szA b 0 szB
+    unsafeFreezePrimArray c
+
+emptyPrimArray :: PrimArray a
+{-# NOINLINE emptyPrimArray #-}
+emptyPrimArray = runST $ primitive $ \s0# -> case newByteArray# 0# s0# of
+  (# s1#, arr# #) -> case unsafeFreezeByteArray# arr# s1# of
+    (# s2#, arr'# #) -> (# s2#, PrimArray arr'# #)
+
+singletonPrimArray :: Prim a => a -> PrimArray a
+singletonPrimArray a = runST $ do
+  arr <- newPrimArray 1
+  writePrimArray arr 0 a
+  unsafeFreezePrimArray arr
+
+
 newPrimArray :: forall m a. (PrimMonad m, Prim a) => Int -> m (MutablePrimArray (PrimState m) a)
 {-# INLINE newPrimArray #-}
 newPrimArray (I# n#)
@@ -104,6 +178,44 @@
       (n# *# (sizeOf# (undefined :: a)))
     )
 
+-- | Copy a slice of an immutable primitive array to an address.
+-- The offset and length are given in elements of type @a@.
+copyPrimArrayToPtr :: forall m a. (PrimMonad m, Prim a)
+  => Ptr a                            -- ^ destination pointer
+  -> PrimArray a                      -- ^ source array
+  -> Int                              -- ^ offset into source array
+  -> Int                              -- ^ number of prims to copy
+  -> m ()
+{-# INLINE copyPrimArrayToPtr #-}
+copyPrimArrayToPtr (Ptr addr#) (PrimArray ba#) (I# soff#) (I# n#) =
+    primitive (\ s# ->
+        let s'# = copyByteArrayToAddr# ba# (soff# *# siz#) addr# (n# *# siz#) s#
+        in (# s'#, () #))
+  where siz# = sizeOf# (undefined :: a)
+
+copyPtrToMutablePrimArray :: forall m a. (PrimMonad m, Prim a)
+  => MutablePrimArray (PrimState m) a
+  -> Int
+  -> Ptr a
+  -> Int
+  -> m ()
+{-# INLINE copyPtrToMutablePrimArray #-}
+copyPtrToMutablePrimArray (MutablePrimArray ba#) (I# doff#) (Ptr addr#) (I# n#) = 
+  primitive (\ s# ->
+      let s'# = copyAddrToByteArray# addr# ba# (doff# *# siz#) (n# *# siz#) s#
+      in (# s'#, () #))
+  where siz# = sizeOf# (undefined :: a)
+
+copyPtrToPrimArray :: forall a. Prim a
+  => Ptr a
+  -> Int
+  -> PrimArray a
+{-# INLINE copyPtrToPrimArray #-}
+copyPtrToPrimArray ptr len = runST $ do
+  arr <- newPrimArray len
+  copyPtrToMutablePrimArray arr 0 ptr len
+  unsafeFreezePrimArray arr
+
 -- | Fill a slice of a mutable byte array with a value.
 setPrimArray
   :: (Prim a, PrimMonad m)
@@ -154,3 +266,8 @@
 indexPrimArray :: forall a. Prim a => PrimArray a -> Int -> a
 {-# INLINE indexPrimArray #-}
 indexPrimArray (PrimArray arr#) (I# i#) = indexByteArray# arr# i#
+
+sizeofPrimArray :: forall a. Prim a => PrimArray a -> Int
+{-# INLINE sizeofPrimArray #-}
+sizeofPrimArray (PrimArray arr#) = I# (quotInt# (sizeofByteArray# arr#) (sizeOf# (undefined :: a)))
+
