diff --git a/src/Data/Text/Zipper.hs b/src/Data/Text/Zipper.hs
--- a/src/Data/Text/Zipper.hs
+++ b/src/Data/Text/Zipper.hs
@@ -48,6 +48,7 @@
 import Data.Monoid
 import qualified Data.Text as T
 import qualified Data.Vector as V
+import qualified Data.Text.Zipper.Vector as V
 
 data TextZipper a =
     TZ { toLeft :: a
@@ -371,13 +372,7 @@
 -- |Construct a zipper from vectors of characters.
 vectorZipper :: [V.Vector Char] -> Maybe Int -> TextZipper (V.Vector Char)
 vectorZipper =
-    let vecLines v | V.null v  = []
-                   | otherwise = case V.elemIndex '\n' v of
-                       Nothing -> [v]
-                       Just i -> let (h, t) = V.splitAt i v
-                                 in h : vecLines t
-
-    in mkZipper V.singleton V.drop V.take V.length V.last V.init V.null vecLines
+    mkZipper V.singleton V.drop V.take V.length V.last V.init V.null V.vecLines
 
 -- |Empty a zipper.
 clearZipper :: (Monoid a) => TextZipper a -> TextZipper a
diff --git a/src/Data/Text/Zipper/Generic.hs b/src/Data/Text/Zipper/Generic.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Text/Zipper/Generic.hs
@@ -0,0 +1,61 @@
+{-# LANGUAGE FlexibleInstances #-}
+module Data.Text.Zipper.Generic
+    ( GenericTextZipper(..)
+    , Data.Text.Zipper.Generic.textZipper
+    )
+where
+
+import qualified Prelude
+import           Prelude hiding (drop, take, length, last, init, null, lines)
+import qualified Data.Text as T
+import qualified Data.Text.Zipper.Vector as V
+import qualified Data.Vector as V
+
+import           Data.Monoid ()
+
+import           Data.Text.Zipper
+
+class Monoid a => GenericTextZipper a where
+  singleton :: Char -> a
+  drop      :: Int -> a -> a
+  take      :: Int -> a -> a
+  length    :: a -> Int
+  last      :: a -> Char
+  init      :: a -> a
+  null      :: a -> Bool
+  lines     :: a -> [a]
+
+instance GenericTextZipper [Char] where
+  singleton = (:[])
+  drop      = Prelude.drop
+  take      = Prelude.take
+  length    = Prelude.length
+  last      = Prelude.last
+  init      = Prelude.init
+  null      = Prelude.null
+  lines     = Prelude.lines
+
+instance GenericTextZipper T.Text where
+  singleton = T.singleton
+  drop      = T.drop
+  take      = T.take
+  length    = T.length
+  last      = T.last
+  init      = T.init
+  null      = T.null
+  lines     = T.lines
+
+instance GenericTextZipper (V.Vector Char) where
+  singleton = V.singleton
+  drop      = V.drop
+  take      = V.take
+  length    = V.length
+  last      = V.last
+  init      = V.init
+  null      = V.null
+  lines     = V.vecLines
+
+textZipper :: GenericTextZipper a =>
+              [a] -> Maybe Int -> TextZipper a
+textZipper =
+  mkZipper singleton drop take length last init null lines
diff --git a/src/Data/Text/Zipper/Vector.hs b/src/Data/Text/Zipper/Vector.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Text/Zipper/Vector.hs
@@ -0,0 +1,14 @@
+module Data.Text.Zipper.Vector
+    ( vecLines
+    )
+where
+
+import qualified Data.Vector as V
+
+vecLines :: V.Vector Char -> [V.Vector Char]
+vecLines v | V.null v  = []
+           | otherwise = case V.elemIndex '\n' v of
+               Nothing -> [v]
+               Just i -> let (h, t) = V.splitAt i v
+                         in h : vecLines t
+
diff --git a/text-zipper.cabal b/text-zipper.cabal
--- a/text-zipper.cabal
+++ b/text-zipper.cabal
@@ -1,5 +1,5 @@
 name:                text-zipper
-version:             0.6.1
+version:             0.7
 synopsis:            A text editor zipper library
 description:         This library provides a zipper and API for editing text.
 license:             BSD3
@@ -18,6 +18,10 @@
 library
   exposed-modules:
     Data.Text.Zipper
+    Data.Text.Zipper.Generic
+
+  other-modules:
+    Data.Text.Zipper.Vector
 
   build-depends:       base < 5,
                        text,
