diff --git a/Data/Text.hs b/Data/Text.hs
index 4a8a81030774b6462e43390ba370d815770db93b..b9592e7e4ec18db8beb086b3dcc374c3ea2cb607 100644
--- a/Data/Text.hs
+++ b/Data/Text.hs
@@ -211,15 +211,15 @@ import Data.String (IsString(..))
 import qualified Data.Text.Internal.Fusion as S
 import qualified Data.Text.Internal.Fusion.Common as S
 import Data.Text.Internal.Fusion (stream, reverseStream, unstream)
-import Data.Text.Private (span_)
+import Data.Text.Internal.Private (span_)
 import Data.Text.Internal (Text(..), empty, firstf, safe, text, textP)
 import qualified Prelude as P
 import Data.Text.Unsafe (Iter(..), iter, iter_, lengthWord16, reverseIter,
                          unsafeHead, unsafeTail)
-import Data.Text.UnsafeChar (unsafeChr)
-import qualified Data.Text.Util as U
+import Data.Text.Internal.Unsafe.Char (unsafeChr)
+import qualified Data.Text.Internal.Functions as F
 import qualified Data.Text.Internal.Encoding.Utf16 as U16
-import Data.Text.Search (indices)
+import Data.Text.Internal.Search (indices)
 #if defined(__HADDOCK__)
 import Data.ByteString (ByteString)
 import qualified Data.Text.Lazy as L
@@ -597,7 +597,7 @@ map f t = unstream (S.map (safe . f) (stream t))
 -- 'Text's and concatenates the list after interspersing the first
 -- argument between each element of the list.
 intercalate :: Text -> [Text] -> Text
-intercalate t = concat . (U.intersperse t)
+intercalate t = concat . (F.intersperse t)
 {-# INLINE intercalate #-}
 
 -- | /O(n)/ The 'intersperse' function takes a character and places it
diff --git a/Data/Text/Array.hs b/Data/Text/Array.hs
index e2c4274fcd7a3baa9cdd7966719f0d7a08fc8c0b..ca614eef39ad40615497a075370f4861e058ab71 100644
--- a/Data/Text/Array.hs
+++ b/Data/Text/Array.hs
@@ -66,8 +66,8 @@ import Control.Monad.ST.Unsafe (unsafeIOToST)
 import Control.Monad.ST (unsafeIOToST)
 #endif
 import Data.Bits ((.&.), xor)
-import Data.Text.Unsafe.Base (inlinePerformIO)
-import Data.Text.UnsafeShift (shiftL, shiftR)
+import Data.Text.Internal.Unsafe (inlinePerformIO)
+import Data.Text.Internal.Unsafe.Shift (shiftL, shiftR)
 #if __GLASGOW_HASKELL__ >= 703
 import Foreign.C.Types (CInt(CInt), CSize(CSize))
 #else
diff --git a/Data/Text/Encoding.hs b/Data/Text/Encoding.hs
index 361f8e276b83334200f9ef2bf15ddb89ade0e40a..81f995cfe8f57dda63ab19e731dd719889264942 100644
--- a/Data/Text/Encoding.hs
+++ b/Data/Text/Encoding.hs
@@ -70,9 +70,9 @@ import Data.ByteString.Internal as B
 import Data.Text ()
 import Data.Text.Encoding.Error (OnDecodeError, UnicodeException, strictDecode)
 import Data.Text.Internal (Text(..), safe, textP)
-import Data.Text.Private (runText)
-import Data.Text.UnsafeChar (ord, unsafeWrite)
-import Data.Text.UnsafeShift (shiftL, shiftR)
+import Data.Text.Internal.Private (runText)
+import Data.Text.Internal.Unsafe.Char (ord, unsafeWrite)
+import Data.Text.Internal.Unsafe.Shift (shiftL, shiftR)
 import Data.Word (Word8, Word32)
 import Foreign.C.Types (CSize)
 import Foreign.ForeignPtr (withForeignPtr)
diff --git a/Data/Text/Internal.hs b/Data/Text/Internal.hs
index 221d1e7ddabb643f5f11d69bfe64385cc480affb..f6560a9990ffe1cae9306659bc17bf304bcd025a 100644
--- a/Data/Text/Internal.hs
+++ b/Data/Text/Internal.hs
@@ -43,7 +43,7 @@ import Control.Exception (assert)
 #endif
 import Data.Bits ((.&.))
 import qualified Data.Text.Array as A
-import Data.Text.UnsafeChar (ord)
+import Data.Text.Internal.Unsafe.Char (ord)
 import Data.Typeable (Typeable)
 
 -- | A space efficient, packed, unboxed Unicode text type.
diff --git a/Data/Text/Internal/Builder.hs b/Data/Text/Internal/Builder.hs
index 6639441e1193caa0204cfd95b51d7fdfa1f26057..3a35998d62c270572fb781bbf60361b846fc0f53 100644
--- a/Data/Text/Internal/Builder.hs
+++ b/Data/Text/Internal/Builder.hs
@@ -56,10 +56,10 @@ import Control.Monad.ST (ST, runST)
 import Data.Bits ((.&.))
 import Data.Monoid (Monoid(..))
 import Data.Text.Internal (Text(..))
-import Data.Text.Lazy.Internal (smallChunkSize)
+import Data.Text.Internal.Lazy (smallChunkSize)
 import Data.Text.Unsafe (inlineInterleaveST)
-import Data.Text.UnsafeChar (ord, unsafeWrite)
-import Data.Text.UnsafeShift (shiftR)
+import Data.Text.Internal.Unsafe.Char (ord, unsafeWrite)
+import Data.Text.Internal.Unsafe.Shift (shiftR)
 import Prelude hiding (map, putChar)
 
 import qualified Data.String as String
diff --git a/Data/Text/Internal/Encoding/Fusion.hs b/Data/Text/Internal/Encoding/Fusion.hs
index 2717b4e157e24c6666e5614be423d339aefd14b8..4c6e3f6c7d221c67e5c2c12d7352d773ea2af001 100644
--- a/Data/Text/Internal/Encoding/Fusion.hs
+++ b/Data/Text/Internal/Encoding/Fusion.hs
@@ -39,8 +39,8 @@ import Data.Text.Internal.Fusion (Step(..), Stream(..))
 import Data.Text.Internal.Fusion.Size
 import Data.Text.Encoding.Error
 import Data.Text.Internal.Encoding.Fusion.Common
-import Data.Text.UnsafeChar (unsafeChr, unsafeChr8, unsafeChr32)
-import Data.Text.UnsafeShift (shiftL, shiftR)
+import Data.Text.Internal.Unsafe.Char (unsafeChr, unsafeChr8, unsafeChr32)
+import Data.Text.Internal.Unsafe.Shift (shiftL, shiftR)
 import Data.Word (Word8, Word16, Word32)
 import Foreign.ForeignPtr (withForeignPtr, ForeignPtr)
 import Foreign.Storable (pokeByteOff)
diff --git a/Data/Text/Internal/Encoding/Fusion/Common.hs b/Data/Text/Internal/Encoding/Fusion/Common.hs
index d59d6ac4c1db4a92eee6d594ac024fc428f30e3f..dd4e40ff7348cfbbff4d23a2c814744fc8b9609c 100644
--- a/Data/Text/Internal/Encoding/Fusion/Common.hs
+++ b/Data/Text/Internal/Encoding/Fusion/Common.hs
@@ -30,8 +30,8 @@ module Data.Text.Internal.Encoding.Fusion.Common
 import Data.Bits ((.&.))
 import Data.Text.Internal.Fusion (Step(..), Stream(..))
 import Data.Text.Internal.Fusion.Types (RS(..))
-import Data.Text.UnsafeChar (ord)
-import Data.Text.UnsafeShift (shiftR)
+import Data.Text.Internal.Unsafe.Char (ord)
+import Data.Text.Internal.Unsafe.Shift (shiftR)
 import Data.Word (Word8)
 
 restreamUtf16BE :: Stream Char -> Stream Word8
diff --git a/Data/Text/Internal/Encoding/Utf8.hs b/Data/Text/Internal/Encoding/Utf8.hs
index 9b3cf8e362a9f835badc723ade93ab892656c8b8..ebcf70762e700b9070133b6c153af5f18b16c758 100644
--- a/Data/Text/Internal/Encoding/Utf8.hs
+++ b/Data/Text/Internal/Encoding/Utf8.hs
@@ -34,8 +34,8 @@ module Data.Text.Internal.Encoding.Utf8
 import Control.Exception (assert)
 #endif
 import Data.Bits ((.&.))
-import Data.Text.UnsafeChar (ord)
-import Data.Text.UnsafeShift (shiftR)
+import Data.Text.Internal.Unsafe.Char (ord)
+import Data.Text.Internal.Unsafe.Shift (shiftR)
 import GHC.Exts
 import GHC.Word (Word8(..))
 
diff --git a/Data/Text/Util.hs b/Data/Text/Internal/Functions.hs
similarity index 86%
rename from Data/Text/Util.hs
rename to Data/Text/Internal/Functions.hs
index f28337147e67c53116e1579966de51980575681f..6c5d2223c03c1e5a23697b80b70824d68cad7b01 100644
--- a/Data/Text/Util.hs
+++ b/Data/Text/Internal/Functions.hs
@@ -1,7 +1,7 @@
 {-# LANGUAGE CPP, DeriveDataTypeable #-}
 
 -- |
--- Module      : Data.Text.Util
+-- Module      : Data.Text.Internal.Functions
 -- Copyright   : 2010 Bryan O'Sullivan
 --
 -- License     : BSD-style
@@ -11,7 +11,7 @@
 --
 -- Useful functions.
 
-module Data.Text.Util
+module Data.Text.Internal.Functions
     (
       intersperse
     ) where
diff --git a/Data/Text/Internal/Fusion.hs b/Data/Text/Internal/Fusion.hs
index ef3ed27b95f9be39a5e7deebba68d0d4e4cbebc1..65b8650d38f834405de0bfaacfe8c3654c2a306e 100644
--- a/Data/Text/Internal/Fusion.hs
+++ b/Data/Text/Internal/Fusion.hs
@@ -51,9 +51,9 @@ import Prelude (Bool(..), Char, Maybe(..), Monad(..), Int,
                 fromIntegral, otherwise)
 import Data.Bits ((.&.))
 import Data.Text.Internal (Text(..))
-import Data.Text.Private (runText)
-import Data.Text.UnsafeChar (ord, unsafeChr, unsafeWrite)
-import Data.Text.UnsafeShift (shiftL, shiftR)
+import Data.Text.Internal.Private (runText)
+import Data.Text.Internal.Unsafe.Char (ord, unsafeChr, unsafeWrite)
+import Data.Text.Internal.Unsafe.Shift (shiftL, shiftR)
 import qualified Data.Text.Array as A
 import qualified Data.Text.Internal.Fusion.Common as S
 import Data.Text.Internal.Fusion.Types
diff --git a/Data/Text/Internal/Lazy.hs b/Data/Text/Internal/Lazy.hs
new file mode 100644
index 0000000000000000000000000000000000000000..0495a258f4897b404d765f66c480c6fc073ae810
--- /dev/null
+++ b/Data/Text/Internal/Lazy.hs
@@ -0,0 +1,118 @@
+{-# LANGUAGE BangPatterns, DeriveDataTypeable #-}
+-- |
+-- Module      : Data.Text.Internal.Lazy
+-- Copyright   : (c) 2009, 2010 Bryan O'Sullivan
+--
+-- License     : BSD-style
+-- Maintainer  : bos@serpentine.com, rtomharper@googlemail.com,
+--               duncan@haskell.org
+-- Stability   : experimental
+-- Portability : GHC
+--
+-- A module containing private 'Text' internals. This exposes the
+-- 'Text' representation and low level construction functions.
+-- Modules which extend the 'Text' system may need to use this module.
+--
+-- You should not use this module unless you are determined to monkey
+-- with the internals, as the functions here do just about nothing to
+-- preserve data invariants.  You have been warned!
+
+module Data.Text.Internal.Lazy
+    (
+      Text(..)
+    , chunk
+    , empty
+    , foldrChunks
+    , foldlChunks
+    -- * Data type invariant and abstraction functions
+
+    -- $invariant
+    , strictInvariant
+    , lazyInvariant
+    , showStructure
+
+    -- * Chunk allocation sizes
+    , defaultChunkSize
+    , smallChunkSize
+    , chunkOverhead
+    ) where
+
+import Data.Text ()
+import Data.Text.Internal.Unsafe.Shift (shiftL)
+import Data.Typeable (Typeable)
+import Foreign.Storable (sizeOf)
+import qualified Data.Text.Internal as T
+
+data Text = Empty
+          | Chunk {-# UNPACK #-} !T.Text Text
+            deriving (Typeable)
+
+-- $invariant
+--
+-- The data type invariant for lazy 'Text': Every 'Text' is either 'Empty' or
+-- consists of non-null 'T.Text's.  All functions must preserve this,
+-- and the QC properties must check this.
+
+-- | Check the invariant strictly.
+strictInvariant :: Text -> Bool
+strictInvariant Empty = True
+strictInvariant x@(Chunk (T.Text _ _ len) cs)
+    | len > 0   = strictInvariant cs
+    | otherwise = error $ "Data.Text.Lazy: invariant violation: "
+                  ++ showStructure x
+
+-- | Check the invariant lazily.
+lazyInvariant :: Text -> Text
+lazyInvariant Empty = Empty
+lazyInvariant x@(Chunk c@(T.Text _ _ len) cs)
+    | len > 0   = Chunk c (lazyInvariant cs)
+    | otherwise = error $ "Data.Text.Lazy: invariant violation: "
+                  ++ showStructure x
+
+-- | Display the internal structure of a lazy 'Text'.
+showStructure :: Text -> String
+showStructure Empty           = "Empty"
+showStructure (Chunk t Empty) = "Chunk " ++ show t ++ " Empty"
+showStructure (Chunk t ts)    =
+    "Chunk " ++ show t ++ " (" ++ showStructure ts ++ ")"
+
+-- | Smart constructor for 'Chunk'. Guarantees the data type invariant.
+chunk :: T.Text -> Text -> Text
+{-# INLINE chunk #-}
+chunk t@(T.Text _ _ len) ts | len == 0 = ts
+                            | otherwise = Chunk t ts
+
+-- | Smart constructor for 'Empty'.
+empty :: Text
+{-# INLINE [0] empty #-}
+empty = Empty
+
+-- | Consume the chunks of a lazy 'Text' with a natural right fold.
+foldrChunks :: (T.Text -> a -> a) -> a -> Text -> a
+foldrChunks f z = go
+  where go Empty        = z
+        go (Chunk c cs) = f c (go cs)
+{-# INLINE foldrChunks #-}
+
+-- | Consume the chunks of a lazy 'Text' with a strict, tail-recursive,
+-- accumulating left fold.
+foldlChunks :: (a -> T.Text -> a) -> a -> Text -> a
+foldlChunks f z = go z
+  where go !a Empty        = a
+        go !a (Chunk c cs) = go (f a c) cs
+{-# INLINE foldlChunks #-}
+
+-- | Currently set to 16 KiB, less the memory management overhead.
+defaultChunkSize :: Int
+defaultChunkSize = 16384 - chunkOverhead
+{-# INLINE defaultChunkSize #-}
+
+-- | Currently set to 128 bytes, less the memory management overhead.
+smallChunkSize :: Int
+smallChunkSize = 128 - chunkOverhead
+{-# INLINE smallChunkSize #-}
+
+-- | The memory management overhead. Currently this is tuned for GHC only.
+chunkOverhead :: Int
+chunkOverhead = sizeOf (undefined :: Int) `shiftL` 1
+{-# INLINE chunkOverhead #-}
diff --git a/Data/Text/Internal/Lazy/Encoding/Fusion.hs b/Data/Text/Internal/Lazy/Encoding/Fusion.hs
index 52ed58d1a27fd056744fb90226adf23bdd181935..8f0b41b7d8b6f98fe7587e538c25a17d343f1dbc 100644
--- a/Data/Text/Internal/Lazy/Encoding/Fusion.hs
+++ b/Data/Text/Internal/Lazy/Encoding/Fusion.hs
@@ -36,8 +36,8 @@ import Data.Text.Internal.Encoding.Fusion.Common
 import Data.Text.Encoding.Error
 import Data.Text.Internal.Fusion (Step(..), Stream(..))
 import Data.Text.Internal.Fusion.Size
-import Data.Text.UnsafeChar (unsafeChr, unsafeChr8, unsafeChr32)
-import Data.Text.UnsafeShift (shiftL)
+import Data.Text.Internal.Unsafe.Char (unsafeChr, unsafeChr8, unsafeChr32)
+import Data.Text.Internal.Unsafe.Shift (shiftL)
 import Data.Word (Word8, Word16, Word32)
 import qualified Data.Text.Internal.Encoding.Utf8 as U8
 import qualified Data.Text.Internal.Encoding.Utf16 as U16
diff --git a/Data/Text/Internal/Lazy/Fusion.hs b/Data/Text/Internal/Lazy/Fusion.hs
index 86c6a4c44685852fd9b2f05cc11c5cf24e6ceb1b..4102c7f94c7679cb998a5b6f860c2f1b1340f2af 100644
--- a/Data/Text/Internal/Lazy/Fusion.hs
+++ b/Data/Text/Internal/Lazy/Fusion.hs
@@ -27,11 +27,11 @@ import qualified Data.Text.Internal.Fusion.Common as S
 import Control.Monad.ST (runST)
 import Data.Text.Internal.Fusion.Types
 import Data.Text.Internal.Fusion.Size (isEmpty, unknownSize)
-import Data.Text.Lazy.Internal
+import Data.Text.Internal.Lazy
 import qualified Data.Text.Internal as I
 import qualified Data.Text.Array as A
-import Data.Text.UnsafeChar (unsafeWrite)
-import Data.Text.UnsafeShift (shiftL)
+import Data.Text.Internal.Unsafe.Char (unsafeWrite)
+import Data.Text.Internal.Unsafe.Shift (shiftL)
 import Data.Text.Unsafe (Iter(..), iter)
 import Data.Int (Int64)
 
diff --git a/Data/Text/Internal/Lazy/Search.hs b/Data/Text/Internal/Lazy/Search.hs
index 5378b07c584e82867678612c9678dc69c06d46fc..30c66946ffd66e4e6467fc042b330ec2330562f8 100644
--- a/Data/Text/Internal/Lazy/Search.hs
+++ b/Data/Text/Internal/Lazy/Search.hs
@@ -24,9 +24,9 @@ import Data.Int (Int64)
 import Data.Word (Word16, Word64)
 import qualified Data.Text.Internal as T
 import Data.Text.Internal.Fusion.Types (PairS(..))
-import Data.Text.Lazy.Internal (Text(..), foldlChunks)
+import Data.Text.Internal.Lazy (Text(..), foldlChunks)
 import Data.Bits ((.|.), (.&.))
-import Data.Text.UnsafeShift (shiftL)
+import Data.Text.Internal.Unsafe.Shift (shiftL)
 
 -- | /O(n+m)/ Find the offsets of all non-overlapping indices of
 -- @needle@ within @haystack@.
diff --git a/Data/Text/Private.hs b/Data/Text/Internal/Private.hs
similarity index 92%
rename from Data/Text/Private.hs
rename to Data/Text/Internal/Private.hs
index 5c70bf28842da9be8b6f2a64105f719105c86541..2416ed963ef55d8071381b9a71221fe22c88ca68 100644
--- a/Data/Text/Private.hs
+++ b/Data/Text/Internal/Private.hs
@@ -1,7 +1,7 @@
 {-# LANGUAGE BangPatterns, Rank2Types, UnboxedTuples #-}
 
 -- |
--- Module      : Data.Text.Private
+-- Module      : Data.Text.Internal.Private
 -- Copyright   : (c) 2011 Bryan O'Sullivan
 --
 -- License     : BSD-style
@@ -9,7 +9,7 @@
 -- Stability   : experimental
 -- Portability : GHC
 
-module Data.Text.Private
+module Data.Text.Internal.Private
     (
       runText
     , span_
diff --git a/Data/Text/Search.hs b/Data/Text/Internal/Search.hs
similarity index 96%
rename from Data/Text/Search.hs
rename to Data/Text/Internal/Search.hs
index 1122177ba86bb5bcebefd6bf75f55f45bd3f33a0..308acd3c7ab927edb1bcb59b8ab39cc96863e0f5 100644
--- a/Data/Text/Search.hs
+++ b/Data/Text/Internal/Search.hs
@@ -1,7 +1,7 @@
 {-# LANGUAGE BangPatterns, ScopedTypeVariables #-}
 
 -- |
--- Module      : Data.Text.Search
+-- Module      : Data.Text.Internal.Search
 -- Copyright   : (c) Bryan O'Sullivan 2009
 --
 -- License     : BSD-style
@@ -27,7 +27,7 @@
 -- * F. Lundh: The Fast Search Algorithm.
 --   <http://effbot.org/zone/stringlib.htm> (2006)
 
-module Data.Text.Search
+module Data.Text.Internal.Search
     (
       indices
     ) where
@@ -36,7 +36,7 @@ import qualified Data.Text.Array as A
 import Data.Word (Word64)
 import Data.Text.Internal (Text(..))
 import Data.Bits ((.|.), (.&.))
-import Data.Text.UnsafeShift (shiftL)
+import Data.Text.Internal.Unsafe.Shift (shiftL)
 
 data T = {-# UNPACK #-} !Word64 :* {-# UNPACK #-} !Int
 
diff --git a/Data/Text/Unsafe/Base.hs b/Data/Text/Internal/Unsafe.hs
similarity index 95%
rename from Data/Text/Unsafe/Base.hs
rename to Data/Text/Internal/Unsafe.hs
index 7907baf0425dec73c9ea2f50a2ecac52745eaf0d..ee8745fe09ab50a33539d022a23e7919c0ef9ad6 100644
--- a/Data/Text/Unsafe/Base.hs
+++ b/Data/Text/Internal/Unsafe.hs
@@ -1,6 +1,6 @@
 {-# LANGUAGE CPP, MagicHash, UnboxedTuples #-}
 -- |
--- Module      : Data.Text.Unsafe.Base
+-- Module      : Data.Text.Internal.Unsafe
 -- Copyright   : (c) 2009, 2010, 2011 Bryan O'Sullivan
 -- License     : BSD-style
 -- Maintainer  : bos@serpentine.com, rtomharper@googlemail.com,
@@ -10,7 +10,7 @@
 --
 -- A module containing unsafe operations, for very very careful use in
 -- heavily tested code.
-module Data.Text.Unsafe.Base
+module Data.Text.Internal.Unsafe
     (
       inlineInterleaveST
     , inlinePerformIO
diff --git a/Data/Text/UnsafeChar.hs b/Data/Text/Internal/Unsafe/Char.hs
similarity index 94%
rename from Data/Text/UnsafeChar.hs
rename to Data/Text/Internal/Unsafe/Char.hs
index e04c2e4f17709cc35b27e23cbb645275b22491cf..e20df0887f3cab653b594c54ddea1c6fc8abcfe9 100644
--- a/Data/Text/UnsafeChar.hs
+++ b/Data/Text/Internal/Unsafe/Char.hs
@@ -1,7 +1,7 @@
 {-# LANGUAGE CPP, MagicHash #-}
 
 -- |
--- Module      : Data.Text.UnsafeChar
+-- Module      : Data.Text.Internal.Unsafe.Char
 -- Copyright   : (c) 2008, 2009 Tom Harper,
 --               (c) 2009, 2010 Bryan O'Sullivan,
 --               (c) 2009 Duncan Coutts
@@ -13,7 +13,7 @@
 -- Portability : GHC
 --
 -- Fast character manipulation functions.
-module Data.Text.UnsafeChar
+module Data.Text.Internal.Unsafe.Char
     (
       ord
     , unsafeChr
@@ -28,7 +28,7 @@ import Control.Exception (assert)
 #endif
 import Control.Monad.ST (ST)
 import Data.Bits ((.&.))
-import Data.Text.UnsafeShift (shiftR)
+import Data.Text.Internal.Unsafe.Shift (shiftR)
 import GHC.Exts (Char(..), Int(..), chr#, ord#, word2Int#)
 import GHC.Word (Word8(..), Word16(..), Word32(..))
 import qualified Data.Text.Array as A
diff --git a/Data/Text/UnsafeShift.hs b/Data/Text/Internal/Unsafe/Shift.hs
similarity index 95%
rename from Data/Text/UnsafeShift.hs
rename to Data/Text/Internal/Unsafe/Shift.hs
index a1e1b3508927fd46d80452328c3ea171f94df24c..0090163c2ea233f0deb8265e23629b0df95d7f53 100644
--- a/Data/Text/UnsafeShift.hs
+++ b/Data/Text/Internal/Unsafe/Shift.hs
@@ -1,7 +1,7 @@
 {-# LANGUAGE MagicHash #-}
 
 -- |
--- Module      : Data.Text.UnsafeShift
+-- Module      : Data.Text.Internal.Unsafe.Shift
 -- Copyright   : (c) Bryan O'Sullivan 2009
 --
 -- License     : BSD-style
@@ -12,7 +12,7 @@
 --
 -- Fast, unchecked bit shifting functions.
 
-module Data.Text.UnsafeShift
+module Data.Text.Internal.Unsafe.Shift
     (
       UnsafeShift(..)
     ) where
diff --git a/Data/Text/Lazy.hs b/Data/Text/Lazy.hs
index 752abfd192a7b2655a8d80c6ae81c38694f93b49..66e751953b80059750078294acdf5f570b6efd13 100644
--- a/Data/Text/Lazy.hs
+++ b/Data/Text/Lazy.hs
@@ -213,9 +213,9 @@ import qualified Data.Text.Unsafe as T
 import qualified Data.Text.Internal.Lazy.Fusion as S
 import Data.Text.Internal.Fusion.Types (PairS(..))
 import Data.Text.Internal.Lazy.Fusion (stream, unstream)
-import Data.Text.Lazy.Internal (Text(..), chunk, empty, foldlChunks, foldrChunks)
+import Data.Text.Internal.Lazy (Text(..), chunk, empty, foldlChunks, foldrChunks)
 import Data.Text.Internal (firstf, safe, textP)
-import qualified Data.Text.Util as U
+import qualified Data.Text.Internal.Functions as F
 import Data.Text.Internal.Lazy.Search (indices)
 #if __GLASGOW_HASKELL__ >= 702
 import qualified GHC.CString as GHC
@@ -561,7 +561,7 @@ map f t = unstream (S.map (safe . f) (stream t))
 -- 'Text's and concatenates the list after interspersing the first
 -- argument between each element of the list.
 intercalate :: Text -> [Text] -> Text
-intercalate t = concat . (U.intersperse t)
+intercalate t = concat . (F.intersperse t)
 {-# INLINE intercalate #-}
 
 -- | /O(n)/ The 'intersperse' function takes a character and places it
diff --git a/Data/Text/Lazy/Encoding.hs b/Data/Text/Lazy/Encoding.hs
index e4a00a751ec1415bfeb2547e2dcf0948aae10808..2af8cf8b0ac80287143553077ae018a6606c5557 100644
--- a/Data/Text/Lazy/Encoding.hs
+++ b/Data/Text/Lazy/Encoding.hs
@@ -50,7 +50,7 @@ module Data.Text.Lazy.Encoding
 
 import Control.Exception (evaluate, try)
 import Data.Text.Encoding.Error (OnDecodeError, UnicodeException, strictDecode)
-import Data.Text.Lazy.Internal (Text(..), chunk, empty, foldrChunks)
+import Data.Text.Internal.Lazy (Text(..), chunk, empty, foldrChunks)
 import qualified Data.ByteString as S
 import qualified Data.ByteString.Lazy as B
 import qualified Data.ByteString.Lazy.Internal as B
diff --git a/Data/Text/Lazy/IO.hs b/Data/Text/Lazy/IO.hs
index cf0fa84228b187639029691694a3813b6f8cf89a..7d4d84fd1e2d899e77a9b7e79a38f13ddc84c217 100644
--- a/Data/Text/Lazy/IO.hs
+++ b/Data/Text/Lazy/IO.hs
@@ -51,7 +51,7 @@ import qualified Control.Exception as E
 import Control.Monad (when)
 import Data.IORef (readIORef)
 import Data.Text.Internal.IO (hGetLineWith, readChunk)
-import Data.Text.Lazy.Internal (chunk, empty)
+import Data.Text.Internal.Lazy (chunk, empty)
 import GHC.IO.Buffer (isEmptyBuffer)
 import GHC.IO.Exception (IOException(..), IOErrorType(..), ioException)
 import GHC.IO.Handle.Internals (augmentIOError, hClose_help,
diff --git a/Data/Text/Lazy/Internal.hs b/Data/Text/Lazy/Internal.hs
index 8d75b3d98359c6d1dc4778afe403456011939f97..a52cde7d6a54615239dd3e3389a923771a08bf6e 100644
--- a/Data/Text/Lazy/Internal.hs
+++ b/Data/Text/Lazy/Internal.hs
@@ -1,7 +1,7 @@
 {-# LANGUAGE BangPatterns, DeriveDataTypeable #-}
 -- |
 -- Module      : Data.Text.Lazy.Internal
--- Copyright   : (c) 2009, 2010 Bryan O'Sullivan
+-- Copyright   : (c) 2013 Bryan O'Sullivan
 --
 -- License     : BSD-style
 -- Maintainer  : bos@serpentine.com, rtomharper@googlemail.com,
@@ -9,110 +9,13 @@
 -- Stability   : experimental
 -- Portability : GHC
 --
--- A module containing private 'Text' internals. This exposes the
--- 'Text' representation and low level construction functions.
--- Modules which extend the 'Text' system may need to use this module.
---
--- You should not use this module unless you are determined to monkey
--- with the internals, as the functions here do just about nothing to
--- preserve data invariants.  You have been warned!
+-- This module has been renamed to 'Data.Text.Internal.Lazy'. This
+-- name for the module will be removed in the next major release.
 
 module Data.Text.Lazy.Internal
+    {-# DEPRECATED "Use Data.Text.Internal.Lazy instead" #-}
     (
-      Text(..)
-    , chunk
-    , empty
-    , foldrChunks
-    , foldlChunks
-    -- * Data type invariant and abstraction functions
-
-    -- $invariant
-    , strictInvariant
-    , lazyInvariant
-    , showStructure
-
-    -- * Chunk allocation sizes
-    , defaultChunkSize
-    , smallChunkSize
-    , chunkOverhead
+      module Data.Text.Internal.Lazy
     ) where
 
-import Data.Text ()
-import Data.Text.UnsafeShift (shiftL)
-import Data.Typeable (Typeable)
-import Foreign.Storable (sizeOf)
-import qualified Data.Text.Internal as T
-
-data Text = Empty
-          | Chunk {-# UNPACK #-} !T.Text Text
-            deriving (Typeable)
-
--- $invariant
---
--- The data type invariant for lazy 'Text': Every 'Text' is either 'Empty' or
--- consists of non-null 'T.Text's.  All functions must preserve this,
--- and the QC properties must check this.
-
--- | Check the invariant strictly.
-strictInvariant :: Text -> Bool
-strictInvariant Empty = True
-strictInvariant x@(Chunk (T.Text _ _ len) cs)
-    | len > 0   = strictInvariant cs
-    | otherwise = error $ "Data.Text.Lazy: invariant violation: "
-                  ++ showStructure x
-
--- | Check the invariant lazily.
-lazyInvariant :: Text -> Text
-lazyInvariant Empty = Empty
-lazyInvariant x@(Chunk c@(T.Text _ _ len) cs)
-    | len > 0   = Chunk c (lazyInvariant cs)
-    | otherwise = error $ "Data.Text.Lazy: invariant violation: "
-                  ++ showStructure x
-
--- | Display the internal structure of a lazy 'Text'.
-showStructure :: Text -> String
-showStructure Empty           = "Empty"
-showStructure (Chunk t Empty) = "Chunk " ++ show t ++ " Empty"
-showStructure (Chunk t ts)    =
-    "Chunk " ++ show t ++ " (" ++ showStructure ts ++ ")"
-
--- | Smart constructor for 'Chunk'. Guarantees the data type invariant.
-chunk :: T.Text -> Text -> Text
-{-# INLINE chunk #-}
-chunk t@(T.Text _ _ len) ts | len == 0 = ts
-                            | otherwise = Chunk t ts
-
--- | Smart constructor for 'Empty'.
-empty :: Text
-{-# INLINE [0] empty #-}
-empty = Empty
-
--- | Consume the chunks of a lazy 'Text' with a natural right fold.
-foldrChunks :: (T.Text -> a -> a) -> a -> Text -> a
-foldrChunks f z = go
-  where go Empty        = z
-        go (Chunk c cs) = f c (go cs)
-{-# INLINE foldrChunks #-}
-
--- | Consume the chunks of a lazy 'Text' with a strict, tail-recursive,
--- accumulating left fold.
-foldlChunks :: (a -> T.Text -> a) -> a -> Text -> a
-foldlChunks f z = go z
-  where go !a Empty        = a
-        go !a (Chunk c cs) = go (f a c) cs
-{-# INLINE foldlChunks #-}
-
--- | Currently set to 16 KiB, less the memory management overhead.
-defaultChunkSize :: Int
-defaultChunkSize = 16384 - chunkOverhead
-{-# INLINE defaultChunkSize #-}
-
--- | Currently set to 128 bytes, less the memory management overhead.
-smallChunkSize :: Int
-smallChunkSize = 128 - chunkOverhead
-{-# INLINE smallChunkSize #-}
-
--- | The memory management overhead. Currently this is tuned for GHC only.
-chunkOverhead :: Int
-chunkOverhead = sizeOf (undefined :: Int) `shiftL` 1
-{-# INLINE chunkOverhead #-}
+import Data.Text.Internal.Lazy
diff --git a/Data/Text/Read.hs b/Data/Text/Read.hs
index f7d721cbf2729a737b61c79bdaa8ad5082822965..b05a8081bc726a541deb1fd3ad75c40b090496b4 100644
--- a/Data/Text/Read.hs
+++ b/Data/Text/Read.hs
@@ -28,7 +28,7 @@ import Data.Char (isDigit, isHexDigit, ord)
 import Data.Int (Int8, Int16, Int32, Int64)
 import Data.Ratio ((%))
 import Data.Text as T
-import Data.Text.Private (span_)
+import Data.Text.Internal.Private (span_)
 import Data.Word (Word, Word8, Word16, Word32, Word64)
 
 -- | Read some text.  If the read succeeds, return its value and the
diff --git a/Data/Text/Unsafe.hs b/Data/Text/Unsafe.hs
index e1307780c7ace707b9c5cded501f0ef84bf8315e..ffd058bad2af2e4d988f804d635c39edd4af187a 100644
--- a/Data/Text/Unsafe.hs
+++ b/Data/Text/Unsafe.hs
@@ -31,8 +31,8 @@ import Control.Exception (assert)
 #endif
 import Data.Text.Internal.Encoding.Utf16 (chr2)
 import Data.Text.Internal (Text(..))
-import Data.Text.Unsafe.Base (inlineInterleaveST, inlinePerformIO)
-import Data.Text.UnsafeChar (unsafeChr)
+import Data.Text.Internal.Unsafe (inlineInterleaveST, inlinePerformIO)
+import Data.Text.Internal.Unsafe.Char (unsafeChr)
 import qualified Data.Text.Array as A
 import GHC.IO (unsafeDupablePerformIO)
 
diff --git a/tests/Tests/Properties.hs b/tests/Tests/Properties.hs
index 2f504f14da9f5a0e2b6a8ec0b1bf46134a08f4c3..69d321893851a3f40b703c000556002dd1281a93 100644
--- a/tests/Tests/Properties.hs
+++ b/tests/Tests/Properties.hs
@@ -24,7 +24,7 @@ import Data.Text.Foreign
 import Data.Text.Internal.Fusion.Size
 import Data.Text.Lazy.Read as TL
 import Data.Text.Read as T
-import Data.Text.Search (indices)
+import Data.Text.Internal.Search (indices)
 import Data.Word (Word, Word8, Word16, Word32, Word64)
 import Numeric (showHex)
 import Test.Framework (Test, testGroup)
@@ -46,7 +46,7 @@ import qualified Data.Text.Lazy.Encoding as EL
 import qualified Data.Text.Internal.Lazy.Fusion as SL
 import qualified Data.Text.Lazy.IO as TL
 import qualified Data.Text.Internal.Lazy.Search as S (indices)
-import qualified Data.Text.UnsafeShift as U
+import qualified Data.Text.Internal.Unsafe.Shift as U
 import qualified System.IO as IO
 
 import Tests.QuickCheckUtils
diff --git a/tests/Tests/QuickCheckUtils.hs b/tests/Tests/QuickCheckUtils.hs
index b27299955af00475a1f72e887ad454c5f4e09c06..1920142fa844351cd6f38c3b5496c98034119d86 100644
--- a/tests/Tests/QuickCheckUtils.hs
+++ b/tests/Tests/QuickCheckUtils.hs
@@ -47,7 +47,7 @@ import qualified Data.Text.Internal.Fusion as TF
 import qualified Data.Text.Internal.Fusion.Common as TF
 import qualified Data.Text.Lazy as TL
 import qualified Data.Text.Internal.Lazy.Fusion as TLF
-import qualified Data.Text.Lazy.Internal as TL
+import qualified Data.Text.Internal.Lazy as TL
 import qualified System.IO as IO
 
 import Tests.Utils
diff --git a/tests/text-tests.cabal b/tests/text-tests.cabal
index e735ca8d9d423a39d4c8f67276c6bb9dec9c7f72..5bced7573df2495dc0309c3e6c0401557ab31363 100644
--- a/tests/text-tests.cabal
+++ b/tests/text-tests.cabal
@@ -96,17 +96,17 @@ library
     Data.Text.Internal.Lazy.Encoding.Fusion
     Data.Text.Internal.Lazy.Fusion
     Data.Text.Lazy.IO
-    Data.Text.Lazy.Internal
+    Data.Text.Internal.Lazy
     Data.Text.Lazy.Read
     Data.Text.Internal.Lazy.Search
-    Data.Text.Private
+    Data.Text.Internal.Private
     Data.Text.Read
-    Data.Text.Search
+    Data.Text.Internal.Search
     Data.Text.Unsafe
-    Data.Text.Unsafe.Base
-    Data.Text.UnsafeChar
-    Data.Text.UnsafeShift
-    Data.Text.Util
+    Data.Text.Internal.Unsafe
+    Data.Text.Internal.Unsafe.Char
+    Data.Text.Internal.Unsafe.Shift
+    Data.Text.Internal.Functions
 
   if flag(hpc)
     ghc-options:
diff --git a/text.cabal b/text.cabal
index 5962aaac74713b98008c5640c69d10fc21a5ffb9..93aaac9511d7734219faec79a23b4726113e4193 100644
--- a/text.cabal
+++ b/text.cabal
@@ -89,6 +89,7 @@ library
     Data.Text.Lazy.Encoding
     Data.Text.Lazy.IO
     Data.Text.Lazy.Internal
+    Data.Text.Internal.Lazy
     Data.Text.Lazy.Read
     Data.Text.Read
     Data.Text.Unsafe
@@ -111,12 +112,12 @@ library
     Data.Text.Internal.Lazy.Encoding.Fusion
     Data.Text.Internal.Lazy.Fusion
     Data.Text.Internal.Lazy.Search
-    Data.Text.Private
-    Data.Text.Search
-    Data.Text.Unsafe.Base
-    Data.Text.UnsafeChar
-    Data.Text.UnsafeShift
-    Data.Text.Util
+    Data.Text.Internal.Private
+    Data.Text.Internal.Search
+    Data.Text.Internal.Unsafe
+    Data.Text.Internal.Unsafe.Char
+    Data.Text.Internal.Unsafe.Shift
+    Data.Text.Internal.Functions
 
   build-depends:
     array      >= 0.3,