diff --git a/deferred-folds.cabal b/deferred-folds.cabal
--- a/deferred-folds.cabal
+++ b/deferred-folds.cabal
@@ -1,5 +1,5 @@
 name: deferred-folds
-version: 0.9.12
+version: 0.9.13
 category: Folding
 synopsis: Abstractions over deferred folds
 description:
@@ -36,6 +36,7 @@
     DeferredFolds.Defs.Unfoldr
     DeferredFolds.Defs.UnfoldrM
     DeferredFolds.Prelude
+    DeferredFolds.Util.TextArray
   build-depends:
     base >=4.9 && <5,
     bytestring >=0.10 && <0.12,
@@ -43,6 +44,7 @@
     foldl >=1 && <2,
     hashable >=1 && <2,
     primitive >=0.6.4 && <0.8,
+    text >=1.2 && <1.3,
     transformers >=0.5 && <0.6,
     unordered-containers >=0.2 && <0.3,
     vector >=0.12 && <0.13
diff --git a/library/DeferredFolds/Defs/Unfoldr.hs b/library/DeferredFolds/Defs/Unfoldr.hs
--- a/library/DeferredFolds/Defs/Unfoldr.hs
+++ b/library/DeferredFolds/Defs/Unfoldr.hs
@@ -9,6 +9,8 @@
 import qualified Data.ByteString as ByteString
 import qualified Data.ByteString.Short.Internal as ShortByteString
 import qualified Data.Vector.Generic as GenericVector
+import qualified Data.Text.Internal as TextInternal
+import qualified DeferredFolds.Util.TextArray as TextArrayUtil
 
 
 deriving instance Functor Unfoldr
@@ -342,3 +344,46 @@
           else step sep (step a (next False)))
       (const init)
       True
+
+{-|
+Reproduces the behaviour of 'Data.Text.unpack'.
+
+Implementation is efficient and avoids allocation of an intermediate list.
+-}
+textChars :: Text -> Unfoldr Char
+textChars (TextInternal.Text arr off len) =
+  Unfoldr $ \ step term ->
+    let
+      loop !offset =
+        if offset >= len
+          then term
+          else 
+            TextArrayUtil.iter arr offset $ \ char nextOffset ->
+              step char (loop nextOffset)
+      in loop off
+
+{-|
+Reproduces the behaviour of 'Data.Text.words'.
+
+Implementation is efficient and avoids allocation of an intermediate list.
+-}
+textWords :: Text -> Unfoldr Text
+textWords (TextInternal.Text arr off len) =
+  Unfoldr $ \ step term ->
+    let
+      loop !wordOffset !offset =
+        if offset >= len
+          then if wordOffset == offset
+            then term
+            else step (chunk wordOffset offset) term
+          else
+            TextArrayUtil.iter arr offset $ \ char nextOffset ->
+              if isSpace char
+                then if wordOffset == offset
+                  then loop nextOffset nextOffset
+                  else step (chunk wordOffset offset) (loop nextOffset nextOffset)
+                else loop wordOffset nextOffset
+      in loop off off
+  where
+    chunk startOffset afterEndOffset =
+      TextInternal.Text arr startOffset (afterEndOffset - startOffset)
diff --git a/library/DeferredFolds/Prelude.hs b/library/DeferredFolds/Prelude.hs
--- a/library/DeferredFolds/Prelude.hs
+++ b/library/DeferredFolds/Prelude.hs
@@ -103,3 +103,7 @@
 -- hashable
 -------------------------
 import Data.Hashable as Exports (Hashable)
+
+-- text
+-------------------------
+import Data.Text as Exports (Text)
diff --git a/library/DeferredFolds/Util/TextArray.hs b/library/DeferredFolds/Util/TextArray.hs
new file mode 100644
--- /dev/null
+++ b/library/DeferredFolds/Util/TextArray.hs
@@ -0,0 +1,30 @@
+module DeferredFolds.Util.TextArray
+where
+
+import DeferredFolds.Prelude
+import qualified Data.Text.Internal as TextInternal
+import qualified Data.Text.Internal.Encoding.Utf16 as TextUtf16
+import qualified Data.Text.Internal.Unsafe.Char as TextChar
+import qualified Data.Text.Array as TextArray
+
+
+{-|
+Same as 'Data.Text.Unsafe.iter',
+but operates on the array directly,
+uses a continuation and passes the next offset to it instead of delta.
+-}
+{-# INLINE iter #-}
+iter :: TextArray.Array -> Int -> (Char -> Int -> a) -> a
+iter arr offset cont =
+  let
+    b1 =
+      TextArray.unsafeIndex arr offset
+    in if b1 >= 0xd800 && b1 <= 0xdbff
+      then let
+        b2 =
+          TextArray.unsafeIndex arr (succ offset)
+        char =
+          TextUtf16.chr2 b1 b2
+        in cont char (offset + 2)
+      else
+        cont (TextChar.unsafeChr b1) (offset + 1)
diff --git a/test/Main.hs b/test/Main.hs
--- a/test/Main.hs
+++ b/test/Main.hs
@@ -9,6 +9,7 @@
 import qualified Test.QuickCheck as QuickCheck
 import qualified Test.QuickCheck.Property as QuickCheck
 import qualified DeferredFolds.Unfoldr as Unfoldr
+import qualified Data.Text as Text
 
 
 main =
@@ -28,4 +29,12 @@
     testProperty "intersperse" $ \ (list :: [Char]) -> 
     intersperse ',' list ===
     toList (Unfoldr.intersperse ',' (Unfoldr.foldable list))
+    ,
+    testProperty "textChars" $ \ (text :: Text) ->
+    Text.unpack text ===
+    toList (Unfoldr.textChars text)
+    ,
+    testProperty "textWords" $ \ (text :: Text) ->
+    Text.words text ===
+    toList (Unfoldr.textWords text)
   ]
