diff --git a/Foreign/C/String/Region.hs b/Foreign/C/String/Region.hs
--- a/Foreign/C/String/Region.hs
+++ b/Foreign/C/String/Region.hs
@@ -67,6 +67,14 @@
 import Foreign.C.String ( CString,  CStringLen
                         , CWString, CWStringLen
                         )
+import qualified Foreign.C.String as FCS ( peekCString,  peekCStringLen
+                                         , newCString,   newCStringLen
+                                         , withCString,  withCStringLen
+                                         , newCAString,  newCAStringLen
+                                         , withCAString, withCAStringLen
+                                         , newCWString,  newCWStringLen
+                                         , withCWString, withCWStringLen
+                                         )
 #endif
 
 #ifdef mingw32_HOST_OS
@@ -99,14 +107,14 @@
 
 
 --------------------------------------------------------------------------------
--- Regional C Strings
+-- * Regional C Strings
 --------------------------------------------------------------------------------
 
 -- | Handy type synonym for a regional pointer to an array of C characters
 -- terminated by a NUL.
 --
 -- This should provide a safer replacement for @Foreign.C.String.'CString'@.
-type RegionalCString    r =  RegionalPtr CChar r
+type RegionalCString r =  RegionalPtr CChar r
 
 -- | Handy type synonym for a regional pointer to an array of C characters which
 -- is paired with the length of the array instead of terminated by a NUL.
@@ -117,67 +125,131 @@
 
 
 --------------------------------------------------------------------------------
--- Using a locale-dependent encoding
+-- * Using a locale-dependent encoding
 --------------------------------------------------------------------------------
 
+-- | Marshal a NUL terminated C string into a Haskell string.
+--
+-- Wraps: @Foreign.C.String.'FCS.peekCString'@
 peekCString ∷ (pr `ParentOf` cr, MonadIO cr)
              ⇒ RegionalCString pr → cr String
 peekCString = peekCAString
 
+-- | Marshal a C string with explicit length into a Haskell string.
+--
+-- Wraps: @Foreign.C.String.'FCS.peekCStringLen'@.
 peekCStringLen ∷ (pr `ParentOf` cr, MonadIO cr)
                ⇒ RegionalCStringLen pr → cr String
 peekCStringLen = peekCAStringLen
 
+-- | Marshal a Haskell string into a NUL terminated C string.
+--
+-- The Haskell string may /not/ contain any NUL characters
+--
+-- Wraps: @Foreign.C.String.'FCS.newCString'@.
 newCString ∷ MonadCatchIO pr
            ⇒ String → RegionT s pr (RegionalCString (RegionT s pr))
 newCString = newCAString
 
+-- | Marshal a Haskell string into a C string (ie, character array) with
+-- explicit length information.
+--
+-- Wraps: @Foreign.C.String.'FCS.newCStringLen'@.
 newCStringLen ∷ MonadCatchIO pr
               ⇒ String → RegionT s pr (RegionalCStringLen (RegionT s pr))
 newCStringLen = newCAStringLen
 
+-- | Marshal a Haskell string into a NUL terminated C string using temporary
+-- storage.
+--
+-- * the Haskell string may /not/ contain any NUL characters
+--
+-- * the memory is freed when the subcomputation terminates (either normally or
+--   via an exception).
+--
+-- Wraps: @Foreign.C.String.'FCS.withCString'@.
 withCString ∷ MonadCatchIO pr
             ⇒ String
             → (∀ s. RegionalCString (RegionT s pr) → RegionT s pr α)
             → pr α
 withCString = withCAString
 
+-- | Marshal a Haskell string into a C string (ie, character array) in temporary
+-- storage, with explicit length information.
+--
+-- * the memory is freed when the subcomputation terminates (either normally or
+--   via an exception).
+--
+-- Wraps: @Foreign.C.String.'FCS.withCStringLen'@.
 withCStringLen ∷ MonadCatchIO pr
                ⇒ String
                → (∀ s. RegionalCStringLen (RegionT s pr) → RegionT s pr α)
                → pr α
 withCStringLen = withCAStringLen
 
+-- | Generalizes @Foreign.C.String.'FCS.charIsRepresentable'@ to any
+-- 'MonadIO'.
 charIsRepresentable ∷ MonadIO m ⇒ Char → m Bool
 charIsRepresentable = liftIO ∘ FCS.charIsRepresentable
 
 
 --------------------------------------------------------------------------------
--- Using 8-bit characters
+-- * Using 8-bit characters
 --------------------------------------------------------------------------------
 
+-- | Marshal a NUL terminated C string into a Haskell string.
+--
+-- Wraps: @Foreign.C.String.'FCS.peekCAString'@.
 peekCAString ∷ (pr `ParentOf` cr, MonadIO cr)
              ⇒ RegionalCString pr → cr String
 peekCAString = unsafeWrap FCS.peekCAString
 
+-- | Marshal a C string with explicit length into a Haskell string.
+--
+-- Wraps: @Foreign.C.String.'FCS.peekCAStringLen'@.
 peekCAStringLen ∷ (pr `ParentOf` cr, MonadIO cr)
                 ⇒ RegionalCStringLen pr → cr String
 peekCAStringLen = liftIO ∘ FCS.peekCAStringLen ∘ first unsafePtr
 
+-- | Marshal a Haskell string into a NUL terminated C string.
+--
+-- The Haskell string may /not/ contain any NUL characters
+--
+-- Wraps: @Foreign.C.String.'FCS.newCAString'@.
 newCAString ∷ MonadCatchIO pr
             ⇒ String → RegionT s pr (RegionalCString (RegionT s pr))
 newCAString = newArray0 nUL ∘ charsToCChars
 
+-- | Marshal a Haskell string into a C string (ie, character array) with
+-- explicit length information.
+--
+-- Wraps: @Foreign.C.String.'FCS.newCAStringLen'@.
 newCAStringLen ∷ MonadCatchIO pr
                ⇒ String → RegionT s pr (RegionalCStringLen (RegionT s pr))
 newCAStringLen = newArrayLen ∘ charsToCChars
 
+-- | Marshal a Haskell string into a NUL terminated C string using temporary
+-- storage.
+--
+-- * the Haskell string may /not/ contain any NUL characters
+--
+-- * the memory is freed when the subcomputation terminates (either normally or
+-- via an exception).
+--
+-- Wraps: @Foreign.C.String.'FCS.withCAString'@.
 withCAString ∷ MonadCatchIO pr
              ⇒ String
              → (∀ s. RegionalCString (RegionT s pr) → RegionT s pr α)
              → pr α
 withCAString = withArray0 nUL ∘ charsToCChars
 
+-- | Marshal a Haskell string into a C string (ie, character array) in temporary
+-- storage, with explicit length information.
+--
+-- * the memory is freed when the subcomputation terminates (either normally or
+--   via an exception).
+--
+-- Wraps: @Foreign.C.String.'FCS.withCAStringLen'@.
 withCAStringLen ∷ MonadCatchIO pr
                 ⇒ String
                 → (∀ s. RegionalCStringLen (RegionT s pr) → RegionT s pr α)
@@ -187,7 +259,7 @@
 
 
 --------------------------------------------------------------------------------
--- C wide strings
+-- * C wide strings
 --------------------------------------------------------------------------------
 
 -- | Handy type synonym for a regional pointer to an array of C wide characters
@@ -203,28 +275,61 @@
 -- This should provide a safer replacement for @Foreign.C.String.'CWStringLen'@.
 type RegionalCWStringLen r = (RegionalPtr CWchar r, Int)
 
+-- | Marshal a NUL terminated C wide string into a Haskell string.
+--
+-- Wraps: @Foreign.C.String.'FCS.peekCWString'@.
 peekCWString ∷ (pr `ParentOf` cr, MonadIO cr)
              ⇒ RegionalCWString pr → cr String
 peekCWString = unsafeWrap FCS.peekCWString
 
+-- | Marshal a C wide string with explicit length into a Haskell string.
+--
+-- Wraps: @Foreign.C.String.'FCS.peekCWStringLen'@.
 peekCWStringLen ∷ (pr `ParentOf` cr, MonadIO cr)
                 ⇒ RegionalCWStringLen pr → cr String
 peekCWStringLen = liftIO ∘ FCS.peekCWStringLen ∘ first unsafePtr
 
+-- | Marshal a Haskell string into a NUL terminated C wide string.
+--
+-- The Haskell string may /not/ contain any NUL characters.
+--
+-- Wraps: @Foreign.C.String.'FCS.newCWString'@.
 newCWString ∷ MonadCatchIO pr
             ⇒ String → RegionT s pr (RegionalCWString (RegionT s pr))
 newCWString = newArray0 wNUL ∘ charsToCWchars
 
+-- | Marshal a Haskell string into a C wide string (ie, wide character array)
+-- with explicit length information.
+--
+-- Wraps: @Foreign.C.String.'FCS.newCWStringLen'@.
 newCWStringLen ∷ MonadCatchIO pr
                ⇒ String → RegionT s pr (RegionalCWStringLen (RegionT s pr))
 newCWStringLen = newArrayLen ∘ charsToCWchars
 
+-- | Marshal a Haskell string into a NUL terminated C wide string using
+-- temporary storage.
+--
+-- * the Haskell string may /not/ contain any NUL characters
+--
+-- * the memory is freed when the subcomputation terminates (either
+--   normally or via an exception).
+--
+-- Wraps: @Foreign.C.String.'FCS.withCWString'@.
 withCWString ∷ MonadCatchIO pr
              ⇒ String
              → (∀ s. RegionalCWString (RegionT s pr) → RegionT s pr α)
              → pr α
 withCWString = withArray0 wNUL ∘ charsToCWchars
 
+-- | Marshal a Haskell string into a NUL terminated C wide string using
+-- temporary storage.
+--
+-- * the Haskell string may /not/ contain any NUL characters.
+--
+-- * the memory is freed when the subcomputation terminates (either
+--   normally or via an exception).
+--
+-- Wraps: @Foreign.C.String.'FCS.withCWStringLen'@.
 withCWStringLen ∷ MonadCatchIO pr
                 ⇒ String
                 → (∀ s. RegionalCWStringLen (RegionT s pr) → RegionT s pr α)
@@ -234,7 +339,7 @@
 
 
 --------------------------------------------------------------------------------
--- Utility functions
+-- * Utility functions
 --------------------------------------------------------------------------------
 
 nUL ∷ CChar
diff --git a/Foreign/Marshal/Alloc/Region.hs b/Foreign/Marshal/Alloc/Region.hs
--- a/Foreign/Marshal/Alloc/Region.hs
+++ b/Foreign/Marshal/Alloc/Region.hs
@@ -32,28 +32,33 @@
 --------------------------------------------------------------------------------
 
 -- from base:
-import Prelude                    ( undefined )
-import Data.Function              ( ($) )
-import Data.Int                   ( Int )
-import Foreign.Storable           ( Storable, sizeOf )
+import Control.Monad                          ( (>>=), fail )
+import Data.Function                          ( ($) )
+import Data.Int                               ( Int )
+import Foreign.Storable                       ( Storable, sizeOf )
 
+import Foreign.Marshal.Alloc                  ( free )
+
+import qualified Foreign.Marshal.Alloc as FMA ( mallocBytes )
+
 #ifdef __HADDOCK__
-import qualified Foreign.Marshal.Alloc as FMA ( alloca, allocaBytes
-                                              , malloc, mallocBytes
-                                              )
+import qualified Foreign.Marshal.Alloc as FMA ( alloca, allocaBytes, malloc )
 #endif
 
 -- from base-unicode-symbols:
-import Data.Function.Unicode      ( (∘) )
+import Prelude.Unicode                        ( (⊥) )
 
+-- from transformers:
+import Control.Monad.IO.Class                 ( liftIO )
+
 -- from MonadCatchIO-transformers:
-import Control.Monad.CatchIO      ( MonadCatchIO )
+import Control.Monad.CatchIO                  ( MonadCatchIO, block )
 
 -- from regions:
-import Control.Monad.Trans.Region ( RegionT, open, with )
+import Control.Monad.Trans.Region             ( RegionT, runRegionT )
 
 -- from ourselves:
-import Foreign.Ptr.Region         ( Memory(Memory), RegionalPtr )
+import Foreign.Ptr.Region                     ( RegionalPtr, regionalPtr )
 
 
 --------------------------------------------------------------------------------
@@ -72,7 +77,7 @@
 alloca ∷ ∀ α pr β. (Storable α, MonadCatchIO pr)
        ⇒ (∀ s. RegionalPtr α (RegionT s pr) → RegionT s pr β)
        → pr β
-alloca = allocaBytes $ sizeOf (undefined ∷ α)
+alloca = allocaBytes $ sizeOf ((⊥) ∷ α)
 
 {-| Convenience function which allocates the given number of bytes, applies the
 given continuation function to the resulting regional pointer and runs the
@@ -81,13 +86,13 @@
 This should provide a safer replacement for:
 @Foreign.Marshal.Alloc.'FMA.allocaBytes'@.
 
-Note that: @allocaBytes = 'with' . 'Memory'@
+Note that: @allocaBytes size f = 'runRegionT' $ 'mallocBytes' size >>= f@
 -}
 allocaBytes ∷ ∀ α pr β. MonadCatchIO pr
             ⇒ Int
             → (∀ s. RegionalPtr α (RegionT s pr) → RegionT s pr β)
             → pr β
-allocaBytes = with ∘ Memory
+allocaBytes size f = runRegionT $ mallocBytes size >>= f
 
 
 --------------------------------------------------------------------------------
@@ -104,20 +109,19 @@
 -}
 malloc ∷ ∀ α pr s. (Storable α, MonadCatchIO pr)
        ⇒ RegionT s pr (RegionalPtr α (RegionT s pr))
-malloc = mallocBytes $ sizeOf (undefined ∷ α)
+malloc = mallocBytes $ sizeOf ((⊥) ∷ α)
 
-{-| Convenience function which allocates the given number of bytes and returns a
-regional pointer to them.
+{-| Allocates the given number of bytes and returns a regional pointer to them.
 
 This should provide a safer replacement for:
 @Foreign.Marshal.Alloc.'FMA.mallocBytes'@.
-
-Note that: @mallocBytes = 'open' . 'Memory'@
 -}
 mallocBytes ∷ MonadCatchIO pr
             ⇒ Int
             → RegionT s pr (RegionalPtr α (RegionT s pr))
-mallocBytes = open ∘ Memory
+mallocBytes size = block $ do
+                     ptr ← liftIO $ FMA.mallocBytes size
+                     regionalPtr ptr $ free ptr
 
 -- TODO:
 -- realloc ∷ (Storable β, pr `ParentOf` cr, MonadIO cr)
diff --git a/Foreign/Marshal/Array/Region.hs b/Foreign/Marshal/Array/Region.hs
--- a/Foreign/Marshal/Array/Region.hs
+++ b/Foreign/Marshal/Array/Region.hs
@@ -1,5 +1,6 @@
 {-# LANGUAGE UnicodeSyntax
            , NoImplicitPrelude
+           , CPP
            , RankNTypes
            , ScopedTypeVariables
   #-}
@@ -53,14 +54,12 @@
 --------------------------------------------------------------------------------
 
 -- from base:
-import Prelude                                ( undefined, (*), succ )
+import Prelude                                ( (*), succ )
 import Data.Function                          ( ($), flip, const )
 import Data.Int                               ( Int )
 import Data.List                              ( length )
 import Data.Eq                                ( Eq )
-import Control.Monad                          ( return, (>>=), fail
-                                              , (>>)
-                                              )
+import Control.Monad                          ( return, (>>=), fail, (>>) )
 import System.IO                              ( IO )
 import Foreign.Ptr                            ( Ptr )
 import Foreign.Storable                       ( Storable, sizeOf )
@@ -75,6 +74,7 @@
                                               )
 -- from base-unicode-symbols:
 import Data.Function.Unicode                  ( (∘) )
+import Prelude.Unicode                        ( (⊥) )
 
 -- from transformers:
 import Control.Monad.IO.Class                 ( MonadIO, liftIO )
@@ -90,25 +90,39 @@
 import Foreign.Ptr.Region.Unsafe              ( unsafePtr, unsafeWrap2 )
 import Foreign.Marshal.Alloc.Region           ( mallocBytes, allocaBytes )
 
+#ifdef __HADDOCK__
+import Foreign.Marshal.Alloc.Region           ( malloc, alloca )
+import Foreign.Marshal.Utils.Region           ( new, with )
+#endif
 
+
 --------------------------------------------------------------------------------
--- Allocation
+-- * Allocation
 --------------------------------------------------------------------------------
 
+-- | Allocate storage for the given number of elements of a storable type.
+--
+-- Like 'malloc', but for multiple elements.
 mallocArray ∷ ∀ α s pr. (Storable α, MonadCatchIO pr)
             ⇒ Int → RegionT s pr (RegionalPtr α (RegionT s pr))
-mallocArray size = mallocBytes $ size * sizeOf (undefined ∷ α)
+mallocArray size = mallocBytes $ size * sizeOf ((⊥) ∷ α)
 
+-- | Like 'mallocArray', but add an extra position to hold a special termination
+-- element.
 mallocArray0 ∷ (Storable α, MonadCatchIO pr)
              ⇒ Int → RegionT s pr (RegionalPtr α (RegionT s pr))
 mallocArray0 = mallocArray ∘ succ
 
+-- | Temporarily allocate space for the given number of elements (like 'alloca',
+-- but for multiple elements).
 allocaArray ∷ ∀ α pr β. (Storable α, MonadCatchIO pr)
             ⇒ Int
             → (∀ s. RegionalPtr α (RegionT s pr) → RegionT s pr β)
             → pr β
-allocaArray size = allocaBytes $ size * sizeOf (undefined ∷ α)
+allocaArray size = allocaBytes $ size * sizeOf ((⊥) ∷ α)
 
+-- | Like 'allocaArray', but add an extra position to hold a special termination
+-- element.
 allocaArray0 ∷ ∀ α pr β. (Storable α, MonadCatchIO pr)
              ⇒ Int
              → (∀ s. RegionalPtr α (RegionT s pr) → RegionT s pr β)
@@ -116,12 +130,12 @@
 allocaArray0 = allocaArray ∘ succ
 
 -- TODO:
--- reallocArray ∷ Storable α ⇒ RegionalPtr α pr → Int → cr (RegionalPtr α pr)
+-- reallocArray  ∷ Storable α ⇒ RegionalPtr α pr → Int → cr (RegionalPtr α pr)
 -- reallocArray0 ∷ Storable α ⇒ RegionalPtr α pr → Int → cr (RegionalPtr α pr)
 
 
 --------------------------------------------------------------------------------
--- Marshalling
+-- * Marshalling
 --------------------------------------------------------------------------------
 
 unsafeWrap2flp ∷ MonadIO m
@@ -129,31 +143,48 @@
                → (γ → RegionalPtr α r → m β)
 unsafeWrap2flp = flip ∘ unsafeWrap2 ∘ flip
 
--- | Wraps: @Foreign.Marshal.Array.@'FMA.peekArray'.
+-- | Convert an array of given length into a Haskell list.
+--
+-- (This version traverses the array backwards using an accumulating parameter,
+-- which uses constant stack space. The previous version using @mapM@ needed
+-- linear stack space.)
+--
+-- Wraps: @Foreign.Marshal.Array.'FMA.peekArray'@.
 peekArray ∷ (Storable α, pr `ParentOf` cr, MonadIO cr)
           ⇒ Int → RegionalPtr α pr → cr [α]
 peekArray =  unsafeWrap2flp FMA.peekArray
 
--- | Wraps: @Foreign.Marshal.Array.@'FMA.peekArray0'.
+-- | Convert an array terminated by the given end marker into a Haskell list.
+--
+-- Wraps: @Foreign.Marshal.Array.'FMA.peekArray0'@.
 peekArray0 ∷ (Storable α, Eq α, pr `ParentOf` cr, MonadIO cr)
            ⇒ α → RegionalPtr α pr → cr [α]
 peekArray0 = unsafeWrap2flp FMA.peekArray0
 
--- | Wraps: @Foreign.Marshal.Array.@'FMA.pokeArray'.
+-- | Write the list elements consecutive into memory.
+--
+-- Wraps: @Foreign.Marshal.Array.'FMA.pokeArray'@.
 pokeArray ∷ (Storable α, pr `ParentOf` cr, MonadIO cr)
           ⇒ RegionalPtr α pr → [α] → cr ()
 pokeArray = unsafeWrap2 FMA.pokeArray
 
--- | Wraps: @Foreign.Marshal.Array.@'FMA.pokeArray0'.
+-- | Write the list elements consecutive into memory and terminate them with the
+-- given marker element.
+--
+-- Wraps: @Foreign.Marshal.Array.'FMA.pokeArray0'@.
 pokeArray0 ∷ (Storable α, pr `ParentOf` cr, MonadIO cr)
            ⇒ α → RegionalPtr α pr → [α] → cr ()
 pokeArray0 m rp xs = liftIO $ FMA.pokeArray0 m (unsafePtr rp) xs
 
 
 --------------------------------------------------------------------------------
--- Combined allocation and marshalling
+-- * Combined allocation and marshalling
 --------------------------------------------------------------------------------
 
+-- | Write a list of storable elements into a newly allocated, consecutive
+-- sequence of storable values.
+--
+-- Like 'new', but for multiple elements.
 newArray ∷ (Storable α, MonadCatchIO pr)
          ⇒ [α] → RegionT s pr (RegionalPtr α (RegionT s pr ))
 newArray vals  = do
@@ -161,6 +192,8 @@
   pokeArray ptr vals
   return ptr
 
+-- | Write a list of storable elements into a newly allocated, consecutive
+-- sequence of storable values, where the end is fixed by the given end marker.
 newArray0 ∷ (Storable α, MonadCatchIO pr)
           ⇒ α → [α] → RegionT s pr (RegionalPtr α (RegionT s pr))
 newArray0 marker vals  = do
@@ -168,12 +201,16 @@
   pokeArray0 marker ptr vals
   return ptr
 
+-- | Temporarily store a list of storable values in memory.
+--
+-- Like 'with', but for multiple elements.
 withArray ∷ (Storable α, MonadCatchIO pr)
           ⇒ [α]
           → (∀ s. RegionalPtr α (RegionT s pr) → RegionT s pr β)
           → pr β
 withArray vals = withArrayLen vals ∘ const
 
+-- | Like 'withArray', but a terminator indicates where the array ends.
 withArray0 ∷ (Storable α, MonadCatchIO pr)
            ⇒ α
            → [α]
@@ -181,6 +218,8 @@
            → pr β
 withArray0 marker vals = withArrayLen0 marker vals ∘ const
 
+-- | Like 'withArray', but the action gets the number of values as an additional
+-- parameter.
 withArrayLen ∷ (Storable α, MonadCatchIO pr)
             ⇒ [α]
             → (∀ s. Int → RegionalPtr α (RegionT s pr) → RegionT s pr β)
@@ -193,6 +232,7 @@
   where
     len = length vals
 
+-- | Like 'withArrayLen', but a terminator indicates where the array ends.
 withArrayLen0 ∷ (Storable α, MonadCatchIO pr)
               ⇒ α
               → [α]
@@ -208,35 +248,59 @@
 
 
 --------------------------------------------------------------------------------
--- Copying
+-- * Copying
 --------------------------------------------------------------------------------
 
--- | Wraps: @Foreign.Marshal.Array.@'FMA.copyArray'.
-copyArray ∷ (Storable α, pr `ParentOf` cr, MonadIO cr)
-          ⇒ RegionalPtr α pr → RegionalPtr α pr → Int → cr ()
+-- | Copy the given number of elements from the second array (source) into the
+-- first array (destination); the copied areas may /not/ overlap.
+--
+-- Wraps: @Foreign.Marshal.Array.'FMA.copyArray'@.
+copyArray ∷ ( Storable α
+            , pr1 `ParentOf` cr
+            , pr2 `ParentOf` cr
+            , MonadIO cr
+            )
+          ⇒ RegionalPtr α pr1 -- ^ Destination
+          → RegionalPtr α pr2 -- ^ Source
+          → Int               -- ^ Number of /elements/ to copy.
+          → cr ()
 copyArray rp1 rp2 = liftIO ∘ FMA.copyArray (unsafePtr rp1) (unsafePtr rp2)
 
--- | Wraps: @Foreign.Marshal.Array.@'FMA.moveArray'.
-moveArray ∷ (Storable α, pr `ParentOf` cr, MonadIO cr)
-          ⇒ RegionalPtr α pr → RegionalPtr α pr → Int → cr ()
+-- | Copy the given number of elements from the second array (source) into the
+-- first array (destination); the copied areas /may/ overlap.
+--
+-- Wraps: @Foreign.Marshal.Array.'FMA.moveArray'@.
+moveArray ∷ ( Storable α
+            , pr1 `ParentOf` cr
+            , pr2 `ParentOf` cr
+            , MonadIO cr
+            )
+          ⇒ RegionalPtr α pr1 -- ^ Destination
+          → RegionalPtr α pr1 -- ^ Source
+          → Int               -- ^ Number of /elements/ to move.
+          → cr ()
 moveArray rp1 rp2 = liftIO ∘ FMA.moveArray (unsafePtr rp1) (unsafePtr rp2)
 
 
 --------------------------------------------------------------------------------
--- Finding the length
+-- * Finding the length
 --------------------------------------------------------------------------------
 
--- | Wraps: @Foreign.Marshal.Array.@'FMA.lengthArray0'.
+-- | Return the number of elements in an array, excluding the terminator.
+--
+-- Wraps: @Foreign.Marshal.Array.'FMA.lengthArray0'@.
 lengthArray0 ∷ (Storable α, Eq α, pr `ParentOf` cr, MonadIO cr)
              ⇒ α → RegionalPtr α pr → cr Int
 lengthArray0 = unsafeWrap2flp FMA.lengthArray0
 
 
 --------------------------------------------------------------------------------
--- Indexing
+-- * Indexing
 --------------------------------------------------------------------------------
 
--- | Wraps: @Foreign.Marshal.Array.@'FMA.advancePtr'.
+-- | Advance a pointer into an array by the given number of elements.
+--
+-- Wraps: @Foreign.Marshal.Array.'FMA.advancePtr'@.
 advancePtr ∷ Storable α ⇒ RegionalPtr α pr → Int → RegionalPtr α pr
 advancePtr rp i = mapRegionalPtr (\p → FMA.advancePtr p i) rp
 
diff --git a/Foreign/Marshal/Utils/Region.hs b/Foreign/Marshal/Utils/Region.hs
--- a/Foreign/Marshal/Utils/Region.hs
+++ b/Foreign/Marshal/Utils/Region.hs
@@ -1,5 +1,6 @@
 {-# LANGUAGE UnicodeSyntax
            , NoImplicitPrelude
+           , CPP
            , RankNTypes
   #-}
 
@@ -43,10 +44,16 @@
 import Data.Function                          ( ($) )
 import Data.Int                               ( Int )
 import Control.Monad                          ( return, (>>=), fail, (>>) )
-import Foreign.Storable                       ( Storable )
 import qualified Foreign.Marshal.Utils as FMU ( fromBool,  toBool
                                               , copyBytes, moveBytes
                                               )
+import Foreign.Storable                       ( Storable )
+
+#ifdef __HADDOCK__
+import qualified Foreign.Marshal.Utils as FMU ( with, new )
+import Foreign.Storable                       ( sizeOf )
+#endif
+
 -- from base-unicode-symbols:
 import Data.Function.Unicode                  ( (∘) )
 
@@ -72,10 +79,23 @@
 
 -- ** Combined allocation and marshalling
 
+-- | @'with' val f@ executes the computation @f@, passing as argument a regional
+-- pointer to a temporarily allocated block of memory into which @val@ has been
+-- marshalled (the combination of 'alloca' and 'poke').
+--
+-- The memory is freed when @f@ terminates (either normally or via an
+-- exception).
+--
+-- This provides a safer replacement for @Foreign.Marshal.Utils.'FMU.with'@.
 with ∷ (Storable α, MonadCatchIO pr)
      ⇒ α → (∀ s. RegionalPtr α (RegionT s pr) → RegionT s pr β) → pr β
 with val f = alloca $ \ptr → poke ptr val >> f ptr
 
+-- | Allocate a block of memory and marshal a value into it (the combination of
+-- 'malloc' and 'poke').  The size of the area allocated is determined by the
+-- 'sizeOf' method from the instance of 'Storable' for the appropriate type.
+--
+-- This provides a safer replacement for @Foreign.Marshal.Utils.'FMU.new'@.
 new ∷ (Storable α, MonadCatchIO pr)
     ⇒ α → RegionT s pr (RegionalPtr α (RegionT s pr))
 new val = do ptr ← malloc
@@ -94,22 +114,32 @@
 
 -- ** Haskellish interface to memcpy and memmove
 
+-- | Copies the given number of bytes from the second area (source) into the
+-- first (destination); the copied areas may /not/ overlap
+--
+-- Wraps: @Foreign.Marshal.Utils.'FMU.copyBytes'@.
 copyBytes ∷ ( pr1 `ParentOf` cr
             , pr2 `ParentOf` cr
             , MonadIO cr
             )
           ⇒ RegionalPtr α pr1 -- ^ Destination
           → RegionalPtr α pr2 -- ^ Source
-          → Int → cr ()
+          → Int               -- ^ Number of bytes to copy
+          → cr ()
 copyBytes rp1 rp2 = liftIO ∘ FMU.copyBytes (unsafePtr rp1) (unsafePtr rp2)
 
+-- | Copies the given number of bytes from the second area (source) into the
+-- first (destination); the copied areas /may/ overlap
+--
+-- Wraps: @Foreign.Marshal.Utils.'FMU.moveBytes'@.
 moveBytes ∷ ( pr1 `ParentOf` cr
             , pr2 `ParentOf` cr
             , MonadIO cr
             )
           ⇒ RegionalPtr α pr1 -- ^ Destination
           → RegionalPtr α pr2 -- ^ Source
-          → Int → cr ()
+          → Int               -- ^ Number of bytes to move
+          → cr ()
 moveBytes rp1 rp2 = liftIO ∘ FMU.moveBytes (unsafePtr rp1) (unsafePtr rp2)
 
 
diff --git a/Foreign/Ptr/Region.hs b/Foreign/Ptr/Region.hs
--- a/Foreign/Ptr/Region.hs
+++ b/Foreign/Ptr/Region.hs
@@ -10,23 +10,24 @@
 -------------------------------------------------------------------------------
 
 module Foreign.Ptr.Region
-    ( -- * Memory as a scarce resource
-      Memory(..)
-    , RegionalPtr
+    ( -- * Regional pointers
+      RegionalPtr
 
       {-| Note that this module re-exports the @Control.Monad.Trans.Region@
       module from the @regions@ package which allows you to:
 
-      * 'open' 'Memory' in a 'RegionT'.
-
       * Run a region using 'runRegionT'.
 
       * Concurrently run a region inside another region using 'forkTopRegion'.
 
-       * Duplicate a regional pointer to a parent region using 'dup'.
+      * Duplicate a 'RegionalPtr' to a parent region using 'dup'.
       -}
     , module Control.Monad.Trans.Region
 
+      -- * Constructing regional pointers
+    , regionalPtr
+    , nullPtr
+
       -- *  Pure functions on regional pointers
     , mapRegionalPtr
 
@@ -42,35 +43,86 @@
 --------------------------------------------------------------------------------
 
 -- from base:
-import Data.Int                    ( Int )
-import qualified Foreign.Ptr as FP ( castPtr, plusPtr, alignPtr, minusPtr )
+import Control.Monad                     ( return, (>>=), fail )
+import Data.Function                     ( ($) )
+import Data.Int                          ( Int )
+import Data.Maybe                        ( Maybe(Nothing, Just) )
+import           Foreign.Ptr             ( Ptr )
+import qualified Foreign.Ptr as FP       ( nullPtr
+                                         , castPtr, plusPtr, alignPtr, minusPtr
+                                         )
 
+-- from transformers:
+import Control.Monad.IO.Class            ( MonadIO )
+
 -- from regions:
-import Control.Monad.Trans.Region -- (re-exported entirely)
+import Control.Monad.Trans.Region     -- (re-exported entirely)
+import Control.Monad.Trans.Region.OnExit ( CloseAction, onExit )
 
 -- from ourselves:
-import Foreign.Ptr.Region.Internal ( Memory(..), RegionalPtr, mapRegionalPtr )
-import Foreign.Ptr.Region.Unsafe   ( unsafePtr )
+import Foreign.Ptr.Region.Internal       ( RegionalPtr(RegionalPtr) )
+import Foreign.Ptr.Region.Unsafe         ( unsafePtr )
 
 
 --------------------------------------------------------------------------------
--- Pure functions on regional pointers
+-- * Constructing regional pointers
 --------------------------------------------------------------------------------
 
--- | Wraps: @Foreign.Ptr.@'FP.castPtr'
+-- | Construct a regional pointer from a native pointer and an @IO@ computation
+-- that frees the pointer which is executed when the region exits.
+regionalPtr ∷ MonadIO pr
+            ⇒ Ptr α
+            → CloseAction
+            → RegionT s pr (RegionalPtr α (RegionT s pr))
+regionalPtr ptr freePtr = do ch ← onExit freePtr
+                             return $ RegionalPtr ptr $ Just ch
+
+-- | The constant @nullPtr@ contains a distinguished value of 'RegionalPtr'
+-- that is not associated with a valid memory location.
+--
+-- Note that @nullPtr@ is a pure value. This means it does not perform the
+-- side-effect of registering a 'CloseAction' like @free nullPtr@ in the
+-- 'RegionT' monad.
+nullPtr ∷ RegionalPtr α r
+nullPtr = RegionalPtr FP.nullPtr Nothing
+
+
+--------------------------------------------------------------------------------
+-- * Pure functions on regional pointers
+--------------------------------------------------------------------------------
+
+-- | Apply a /pure/ function to the inner pointer of a regional pointer.
+mapRegionalPtr ∷ (Ptr α → Ptr β) → (RegionalPtr α r → RegionalPtr β r)
+mapRegionalPtr f = \(RegionalPtr ptr ch) → RegionalPtr (f ptr) ch
+
+-- | The @castPtr@ function casts a pointer from one type to another.
+--
+-- Wraps: @Foreign.Ptr.@'FP.castPtr'
 castPtr ∷ RegionalPtr α r → RegionalPtr β r
 castPtr = mapRegionalPtr FP.castPtr
 
--- | Wraps: @Foreign.Ptr.@'FP.plusPtr'
+-- | Advances the given address by the given offset in bytes.
+--
+-- Wraps: @Foreign.Ptr.@'FP.plusPtr'
 plusPtr ∷ RegionalPtr α r → Int → RegionalPtr β r
 plusPtr rp n = mapRegionalPtr (\p → FP.plusPtr p n) rp
 
--- | Wraps: @Foreign.Ptr.@'FP.alignPtr'
+-- | Given an arbitrary address and an alignment constraint, @alignPtr@ yields
+-- the next higher address that fulfills the alignment constraint. An alignment
+-- constraint @x@ is fulfilled by any address divisible by @x@.  This operation
+-- is idempotent.
+--
+-- Wraps: @Foreign.Ptr.@'FP.alignPtr'
 alignPtr ∷ RegionalPtr α r → Int → RegionalPtr α r
 alignPtr rp n = mapRegionalPtr (\p → FP.alignPtr p n) rp
 
--- | Wraps: @Foreign.Ptr.@'FP.minusPtr'
-minusPtr ∷ RegionalPtr α r → RegionalPtr β r → Int
+-- | Computes the offset required to get from the second to the first
+-- argument. We have
+--
+-- > p2 == p1 `plusPtr` (p2 `minusPtr` p1)
+--
+-- Wraps: @Foreign.Ptr.@'FP.minusPtr'
+minusPtr ∷ RegionalPtr α r1 → RegionalPtr β r2 → Int
 minusPtr rp1 rp2 = FP.minusPtr (unsafePtr rp1) (unsafePtr rp2)
 
 
diff --git a/Foreign/Ptr/Region/Internal.hs b/Foreign/Ptr/Region/Internal.hs
--- a/Foreign/Ptr/Region/Internal.hs
+++ b/Foreign/Ptr/Region/Internal.hs
@@ -1,7 +1,6 @@
 {-# LANGUAGE UnicodeSyntax
            , NoImplicitPrelude
-           , TypeFamilies
-           , CPP
+           , KindSignatures
   #-}
 
 -------------------------------------------------------------------------------
@@ -14,12 +13,10 @@
 -------------------------------------------------------------------------------
 
 module Foreign.Ptr.Region.Internal
-    ( -- * Memory as a scarce resource
-      Memory(..)
-    , RegionalPtr
+    ( -- * Regional pointers
+      RegionalPtr(RegionalPtr)
 
       -- * Utility functions for lifting operations on Ptrs to RegionalPtrs
-    , mapRegionalPtr
     , unsafePtr
     , unsafeWrap, unsafeWrap2, unsafeWrap3
     ) where
@@ -30,64 +27,40 @@
 --------------------------------------------------------------------------------
 
 -- from base:
-import Data.Function                          ( ($) )
-import Data.Int                               ( Int )
-import Control.Monad                          ( liftM )
-import System.IO                              ( IO )
-import Foreign.Ptr                            ( Ptr )
-import qualified Foreign.Marshal.Alloc as FMA ( mallocBytes, free )
-
--- from base-unicode-symbols:
-import Data.Function.Unicode                  ( (∘) )
+import Control.Monad ( return, (>>=), fail )
+import Data.Function ( ($) )
+import Data.Maybe    ( Maybe(Nothing, Just) )
+import System.IO     ( IO )
+import Foreign.Ptr   ( Ptr )
 
 -- from transformers:
-import Control.Monad.IO.Class                 ( MonadIO, liftIO )
+import Control.Monad.IO.Class ( MonadIO, liftIO )
 
 -- from regions:
-import Control.Resource                       ( Resource
-                                              , Handle
-                                              , open
-                                              , close
-                                              )
-import Control.Monad.Trans.Region             ( RegionalHandle )
-import Control.Monad.Trans.Region.Unsafe      ( internalHandle
-                                              , mapInternalHandle
-                                              )
-#ifdef __HADDOCK__
-import Control.Monad.Trans.Region ( open )
-#endif
+import Control.Monad.Trans.Region.OnExit ( CloseHandle )
+import Control.Monad.Trans.Region        ( Dup(dup) )
 
 
 --------------------------------------------------------------------------------
--- Memory as a scarce resource
+-- * Regional pointers
 --------------------------------------------------------------------------------
 
-{-| Represents memory of 'size' number of bytes which may be marshalled to or
-from Haskell values of type @&#945;@. Before you can use the memory you have to
-allocate it using 'open'.
--}
-newtype Memory α = Memory { size ∷ Int }
-
-instance Resource (Memory α) where
-    newtype Handle (Memory α) = Pointer { ptr ∷ Ptr α }
-
-    open  = liftM Pointer ∘ FMA.mallocBytes ∘ size
-    close = FMA.free ∘ ptr
+-- | A regional handle to memory. This should provide a safer replacement for
+-- @Foreign.Ptr.'Ptr'@
+data RegionalPtr α (r ∷ * → *) = RegionalPtr (Ptr α) (Maybe (CloseHandle r))
 
--- | Handy type synonym for a regional handle to memory. This should provide a
--- safer replacement for @Foreign.Ptr.@'Ptr'
-type RegionalPtr α r = RegionalHandle (Memory α) r
+instance Dup (RegionalPtr α) where
+    dup (RegionalPtr ptr Nothing)   = return $ RegionalPtr ptr Nothing
+    dup (RegionalPtr ptr (Just ch)) = do ch' ← dup ch
+                                         return $ RegionalPtr ptr $ Just ch'
 
 
 --------------------------------------------------------------------------------
--- Utility functions for lifting operations on Ptrs to RegionalPtrs
+-- * Utility functions for lifting operations on Ptrs to RegionalPtrs
 --------------------------------------------------------------------------------
 
-mapRegionalPtr ∷ (Ptr α → Ptr β) → (RegionalPtr α r → RegionalPtr β r)
-mapRegionalPtr f = mapInternalHandle $ Pointer ∘ f ∘ ptr
-
 unsafePtr ∷ RegionalPtr α r → Ptr α
-unsafePtr = ptr ∘ internalHandle
+unsafePtr (RegionalPtr ptr _) = ptr
 
 unsafeWrap ∷ MonadIO m
            ⇒ (Ptr α → IO β)
diff --git a/Foreign/Ptr/Region/Unsafe.hs b/Foreign/Ptr/Region/Unsafe.hs
--- a/Foreign/Ptr/Region/Unsafe.hs
+++ b/Foreign/Ptr/Region/Unsafe.hs
@@ -7,8 +7,12 @@
 -- License     :  BSD3 (see the file LICENSE)
 -- Maintainer  :  Bas van Dijk <v.dijk.bas@gmail.com>
 --
--- /Unsafe/ functions for retrieving the actual 'Ptr' from a regional pointer
--- and for lifting operations on 'Ptr's to 'RegionalPtr's.
+-- /Unsafe/ functions for retrieving the actual @Ptr@ from a regional pointer
+-- and for lifting operations on @Ptrs@ to @RegionalPtrs@.
+--
+-- These operations are unsafe because they allow you to @free@ the regional
+-- pointer before exiting their region. So they enable you to perform @IO@ with
+-- already freed pointers.
 --
 -------------------------------------------------------------------------------
 
diff --git a/Foreign/Storable/Region.hs b/Foreign/Storable/Region.hs
--- a/Foreign/Storable/Region.hs
+++ b/Foreign/Storable/Region.hs
@@ -45,32 +45,70 @@
 -- Storable methods lifted to a region
 --------------------------------------------------------------------------------
 
--- | Wraps: @Foreign.Storable.'FS.peekElemOff'@.
+-- | Read a value from a memory area regarded as an array of values of the same
+-- kind. The first argument specifies the start address of the array and the
+-- second the index into the array (the first element of the array has index
+-- @0@). The following equality holds,
+--
+-- > peekElemOff addr idx = IOExts.fixIO $ \result ->
+-- >   peek (addr `plusPtr` (idx * sizeOf result))
+--
+-- Note that this is only a specification, not necessarily the concrete
+-- implementation of the function.
+--
+-- Wraps: @Foreign.Storable.'FS.peekElemOff'@.
 peekElemOff ∷ (pr `ParentOf` cr, Storable α, MonadIO cr)
             ⇒ RegionalPtr α pr → Int → cr α
 peekElemOff = unsafeWrap2 FS.peekElemOff
 
--- | Wraps: @Foreign.Storable.'FS.pokeElemOff'@.
+-- | Write a value to a memory area regarded as an array of values of the same
+-- kind.  The following equality holds:
+--
+-- > pokeElemOff addr idx x =
+-- >   poke (addr `plusPtr` (idx * sizeOf x)) x
+--
+-- Wraps: @Foreign.Storable.'FS.pokeElemOff'@.
 pokeElemOff ∷ (pr `ParentOf` cr, Storable α, MonadIO cr)
             ⇒ RegionalPtr α pr → Int → α → cr ()
 pokeElemOff = unsafeWrap3 FS.pokeElemOff
 
--- | Wraps: @Foreign.Storable.'FS.peekByteOff'@.
+-- | Read a value from a memory location given by a base address and offset.
+-- The following equality holds:
+--
+-- > peekByteOff addr off = peek (addr `plusPtr` off)
+--
+-- Wraps: @Foreign.Storable.'FS.peekByteOff'@.
 peekByteOff ∷ (pr `ParentOf` cr, Storable α, MonadIO cr)
             ⇒ RegionalPtr β pr → Int → cr α
 peekByteOff = unsafeWrap2 FS.peekByteOff
 
--- | Wraps: @Foreign.Storable.'FS.pokeByteOff'@.
+-- | Write a value to a memory location given by a base address and offset.  The
+-- following equality holds:
+--
+-- > pokeByteOff addr off x = poke (addr `plusPtr` off) x
+--
+-- Wraps: @Foreign.Storable.'FS.pokeByteOff'@.
 pokeByteOff ∷ (pr `ParentOf` cr, Storable α, MonadIO cr)
             ⇒ RegionalPtr β pr → Int → α → cr ()
 pokeByteOff = unsafeWrap3 FS.pokeByteOff
 
--- | Wraps: @Foreign.Storable.'FS.peek'@.
+-- | Read a value from the given memory location.
+--
+-- Note that the peek and poke functions might require properly aligned
+-- addresses to function correctly.  This is architecture dependent; thus,
+-- portable code should ensure that when peeking or poking values of some type
+-- @a@, the alignment constraint for @a@, as given by the function 'alignment'
+-- is fulfilled.
+--
+-- Wraps: @Foreign.Storable.'FS.peek'@.
 peek ∷ (pr `ParentOf` cr, Storable α, MonadIO cr)
      ⇒ RegionalPtr α pr → cr α
 peek = unsafeWrap FS.peek
 
--- | Wraps: @Foreign.Storable.'FS.poke'@.
+-- | Write the given value to the given memory location.  Alignment restrictions
+-- might apply; see 'peek'.
+--
+-- Wraps: @Foreign.Storable.'FS.poke'@.
 poke ∷ (pr `ParentOf` cr, Storable α, MonadIO cr)
      ⇒ RegionalPtr α pr → α → cr ()
 poke = unsafeWrap2 FS.poke
diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2009 Bas van Dijk
+Copyright (c) 2010 Bas van Dijk
 
 All rights reserved.
 
diff --git a/regional-pointers.cabal b/regional-pointers.cabal
--- a/regional-pointers.cabal
+++ b/regional-pointers.cabal
@@ -1,5 +1,5 @@
 name:          regional-pointers
-version:       0.1.0.2
+version:       0.2
 cabal-version: >=1.6
 build-type:    Custom
 license:       BSD3
@@ -36,7 +36,7 @@
   GHC-Options: -Wall
   build-depends: base                      >= 4     && < 4.3
                , base-unicode-symbols      >= 0.1.1 && < 0.3
-               , regions                   >= 0.5   && < 0.6
+               , regions                   >= 0.6   && < 0.7
                , transformers              >= 0.2   && < 0.3
                , MonadCatchIO-transformers >= 0.2   && < 0.3
   exposed-modules: Foreign.Ptr.Region
@@ -46,6 +46,4 @@
                    Foreign.Marshal.Utils.Region
                    Foreign.Storable.Region
                    Foreign.C.String.Region
-                   -- TODO: Foreign.StablePtr.Region
-                   -- TODO: Foreign.Marshal.Pool.Region
   other-modules:   Foreign.Ptr.Region.Internal
