diff --git a/Data/Builder.hs b/Data/Builder.hs
new file mode 100644
--- /dev/null
+++ b/Data/Builder.hs
@@ -0,0 +1,88 @@
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE FunctionalDependencies #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE FlexibleContexts #-}
+-- | Abstraction for different kinds of builders.
+--
+-- Note that whenever a character encoding is used, it will be UTF8. For
+-- different behavior, please use the underlying library.
+module Data.Builder
+    ( TextBuilder
+    , BlazeBuilder
+    , Builder (..)
+    , ToBuilder (..)
+    , textToBuilder
+    ) where
+
+import Data.Monoid (Monoid)
+
+import qualified Data.Text as T
+import qualified Data.Text.Lazy as TL
+import qualified Data.Text.Lazy.Builder as TB
+
+import qualified Data.ByteString as S
+import qualified Data.ByteString.Lazy as L
+import qualified Blaze.ByteString.Builder as BB
+import qualified Blaze.ByteString.Builder.Char.Utf8 as BB
+
+-- | Since 0.1.0.0
+type TextBuilder = TB.Builder
+
+-- | Since 0.1.0.0
+type BlazeBuilder = BB.Builder
+
+-- | Since 0.1.0.0
+class Monoid builder => Builder builder lazy | builder -> lazy, lazy -> builder where
+    -- | Since 0.1.0.0
+    builderToLazy :: builder -> lazy
+
+    -- | Since 0.1.0.0
+    flushBuilder :: builder
+
+instance Builder TB.Builder TL.Text where
+    builderToLazy = TB.toLazyText
+    flushBuilder = TB.flush
+
+instance Builder BB.Builder L.ByteString where
+    builderToLazy = BB.toLazyByteString
+    flushBuilder = BB.flush
+
+-- | Since 0.1.0.0
+class ToBuilder value builder where
+    -- | Since 0.1.0.0
+    toBuilder :: value -> builder
+
+-- Text
+instance ToBuilder TB.Builder TB.Builder where
+    toBuilder = id
+instance ToBuilder T.Text TB.Builder where
+    toBuilder = TB.fromText
+instance ToBuilder TL.Text TB.Builder where
+    toBuilder = TB.fromLazyText
+instance ToBuilder Char TB.Builder where
+    toBuilder = TB.singleton
+instance (a ~ Char) => ToBuilder [a] TB.Builder where
+    toBuilder = TB.fromString
+
+-- Blaze
+instance ToBuilder BB.Builder BB.Builder where
+    toBuilder = id
+instance ToBuilder T.Text BB.Builder where
+    toBuilder = BB.fromText
+instance ToBuilder TL.Text BB.Builder where
+    toBuilder = BB.fromLazyText
+instance ToBuilder Char BB.Builder where
+    toBuilder = BB.fromChar
+instance (a ~ Char) => ToBuilder [a] BB.Builder where
+    toBuilder = BB.fromString
+
+instance ToBuilder S.ByteString BB.Builder where
+    toBuilder = BB.fromByteString
+instance ToBuilder L.ByteString BB.Builder where
+    toBuilder = BB.fromLazyByteString
+
+-- | Provided for type disambiguation in the presence of OverloadedStrings.
+--
+-- Since 0.1.0.0
+textToBuilder :: ToBuilder T.Text builder => T.Text -> builder
+textToBuilder = toBuilder
diff --git a/Data/ChunkedZip.hs b/Data/ChunkedZip.hs
new file mode 100644
--- /dev/null
+++ b/Data/ChunkedZip.hs
@@ -0,0 +1,172 @@
+-- | Various zipping and unzipping functions for chunked data structures.
+module Data.ChunkedZip where
+
+import Prelude hiding (zipWith, zipWith3)
+import Control.Arrow ((&&&), (***))
+import qualified Data.List as List
+import qualified Data.List.NonEmpty as NonEmpty
+import Data.List.NonEmpty (NonEmpty)
+import qualified Data.Vector as Vector
+-- import qualified Data.Vector.Unboxed as UVector
+import qualified Data.Sequence as Seq
+import Control.Monad.Trans.Identity
+import Control.Monad.Trans.Reader
+import qualified Data.IntMap as IntMap
+import Data.Tree
+import Data.Functor.Compose
+import Data.Foldable (toList)
+
+class Functor f => Zip f where
+    zipWith :: (a -> b -> c) -> f a -> f b -> f c
+
+    zip :: f a -> f b -> f (a, b)
+    zip = zipWith (,)
+
+    zap :: f (a -> b) -> f a -> f b
+    zap = zipWith id
+
+    unzip :: f (a, b) -> (f a, f b)
+    unzip = fmap fst &&& fmap snd
+
+instance Zip [] where
+    zip = List.zip
+    zipWith = List.zipWith
+    unzip = List.unzip
+instance Zip NonEmpty where
+    zipWith = NonEmpty.zipWith
+    zip = NonEmpty.zip
+    unzip = NonEmpty.unzip
+instance Zip Seq.Seq where
+    zip = Seq.zip
+    zipWith = Seq.zipWith
+    unzip = (Seq.fromList *** Seq.fromList) . List.unzip . toList
+instance Zip Tree where
+    zipWith f (Node a as) (Node b bs) = Node (f a b) (zipWith (zipWith f) as bs)
+instance Zip Vector.Vector where
+    zip = Vector.zip
+    unzip = Vector.unzip
+    zipWith = Vector.zipWith
+  {-
+instance Zip UVector where
+    zip = UVector.zip
+    unzip = UVector.unzip
+    zipWith = UVector.zipWith
+    -}
+
+instance Zip m => Zip (IdentityT m) where
+    zipWith f (IdentityT m) (IdentityT n) = IdentityT (zipWith f m n)
+instance Zip ((->)a) where
+    zipWith f g h a = f (g a) (h a)
+instance Zip m => Zip (ReaderT e m) where
+    zipWith f (ReaderT m) (ReaderT n) = ReaderT $ \a ->
+      zipWith f (m a) (n a)
+instance Zip IntMap.IntMap where
+    zipWith = IntMap.intersectionWith
+instance (Zip f, Zip g) => Zip (Compose f g) where
+    zipWith f (Compose a) (Compose b) = Compose $ zipWith (zipWith f) a b
+
+class Functor f => Zip3 f where
+    zipWith3 :: (a -> b -> c -> d) -> f a -> f b -> f c -> f d
+
+    zip3 :: f a -> f b -> f c -> f (a, b, c)
+    zip3 = zipWith3 (\x y z -> (x,y,z))
+
+    zap3 :: f (a -> b -> c) -> f a -> f b -> f c
+    zap3 = zipWith3 id
+
+    unzip3 :: f (a, b, c) -> (f a, f b, f c)
+    -- unzip3 = fmap (\(x,_,_)->x) &&& fmap (\(_,x,_)->x) &&& fmap (\(_,_,x)->x)
+
+instance Zip3 [] where
+    zip3 = List.zip3
+    unzip3 = List.unzip3
+    zipWith3 = List.zipWith3
+instance Zip3 Vector.Vector where
+    zip3 = Vector.zip3
+    unzip3 = Vector.unzip3
+    zipWith3 = Vector.zipWith3
+instance Zip3 Seq.Seq where
+    zip3 = Seq.zip3
+    unzip3 = (\(a, b, c) -> (Seq.fromList a, Seq.fromList b, Seq.fromList c)) . List.unzip3 . toList
+    zipWith3 = Seq.zipWith3
+
+class Functor f => Zip4 f where
+    zipWith4 :: (a -> b -> c -> d -> e) -> f a -> f b -> f c -> f d -> f e
+
+    zip4 :: f a -> f b -> f c -> f d ->  f (a, b, c, d)
+    zip4 = zipWith4 (\w x y z -> (w, x,y,z))
+
+    zap4 :: f (a -> b -> c -> d) -> f a -> f b -> f c -> f d
+    zap4 = zipWith4 id
+
+    unzip4 :: f (a, b, c, d) -> (f a, f b, f c, f d)
+
+instance Zip4 [] where
+    zip4 = List.zip4
+    unzip4 = List.unzip4
+    zipWith4 = List.zipWith4
+instance Zip4 Vector.Vector where
+    zip4 = Vector.zip4
+    unzip4 = Vector.unzip4
+    zipWith4 = Vector.zipWith4
+instance Zip4 Seq.Seq where
+    zip4 = Seq.zip4
+    unzip4 = (\(a, b, c, d) -> (Seq.fromList a, Seq.fromList b, Seq.fromList c, Seq.fromList d)) . List.unzip4 . toList
+    zipWith4 = Seq.zipWith4
+
+class Functor f => Zip5 f where
+    zipWith5 :: (a -> b -> c -> d -> e -> g) -> f a -> f b -> f c -> f d -> f e -> f g
+
+    zip5 :: f a -> f b -> f c -> f d -> f e -> f (a, b, c, d, e)
+    zip5 = zipWith5 (\v w x y z -> (v,w,x,y,z))
+
+    zap5 :: f (a -> b -> c -> d -> e) -> f a -> f b -> f c -> f d -> f e
+    zap5 = zipWith5 id
+
+    unzip5 :: f (a, b, c, d, e) -> (f a, f b, f c, f d, f e)
+
+instance Zip5 [] where
+    zip5 = List.zip5
+    unzip5 = List.unzip5
+    zipWith5 = List.zipWith5
+instance Zip5 Vector.Vector where
+    zip5 = Vector.zip5
+    unzip5 = Vector.unzip5
+    zipWith5 = Vector.zipWith5
+
+class Functor f => Zip6 f where
+    zipWith6 :: (a -> b -> c -> d -> e -> g -> h) -> f a -> f b -> f c -> f d -> f e -> f g -> f h
+
+    zip6 :: f a -> f b -> f c -> f d -> f e -> f g -> f (a, b, c, d, e, g)
+    zip6 = zipWith6 (\u v w x y z -> (u, v,w,x,y,z))
+
+    zap6 :: f (a -> b -> c -> d -> e -> g) -> f a -> f b -> f c -> f d -> f e -> f g
+    zap6 = zipWith6 id
+
+    unzip6 :: f (a, b, c, d, e, g) -> (f a, f b, f c, f d, f e, f g)
+
+instance Zip6 [] where
+    zip6 = List.zip6
+    unzip6 = List.unzip6
+    zipWith6 = List.zipWith6
+instance Zip6 Vector.Vector where
+    zip6 = Vector.zip6
+    unzip6 = Vector.unzip6
+    zipWith6 = Vector.zipWith6
+
+class Functor f => Zip7 f where
+    zipWith7 :: (a -> b -> c -> d -> e -> g -> h -> i) -> f a -> f b -> f c -> f d -> f e -> f g -> f h -> f i
+
+    zip7 :: f a -> f b -> f c -> f d -> f e -> f g -> f h -> f (a, b, c, d, e, g, h)
+    zip7 = zipWith7 (\t u v w x y z -> (t,u,v,w,x,y,z))
+
+    zap7 :: f (a -> b -> c -> d -> e -> g -> h) -> f a -> f b -> f c -> f d -> f e -> f g -> f h
+    zap7 = zipWith7 id
+
+    unzip7 :: f (a, b, c, d, e, g, h) -> (f a, f b, f c, f d, f e, f g, f h)
+    -- unzip3 = fmap (\(x,_,_)->x) &&& fmap (\(_,x,_)->x) &&& fmap (\(_,_,x)->x)
+
+instance Zip7 [] where
+    zip7 = List.zip7
+    unzip7 = List.unzip7
+    zipWith7 = List.zipWith7
diff --git a/Data/IOData.hs b/Data/IOData.hs
new file mode 100644
--- /dev/null
+++ b/Data/IOData.hs
@@ -0,0 +1,88 @@
+{-# LANGUAGE CPP          #-}
+{-# LANGUAGE TypeFamilies #-}
+module Data.IOData where
+
+import           Control.Monad                 (liftM)
+import           Control.Monad.IO.Class
+import qualified Data.ByteString               as ByteString
+import qualified Data.ByteString.Char8         as ByteString8
+import qualified Data.ByteString.Lazy          as LByteString
+import           Data.ByteString.Lazy.Internal (defaultChunkSize)
+import           Data.Sequences                (IsSequence)
+import           Data.Sequences.Lazy           (fromStrict)
+import qualified Data.Text                     as Text
+import qualified Data.Text.IO                  as Text
+import qualified Data.Text.Lazy                as LText
+import qualified Data.Text.Lazy.IO             as LText
+import           Filesystem.Path               (FilePath)
+import qualified Filesystem.Path.CurrentOS     as FilePath
+import           Prelude                       (Char, flip, ($), (.))
+import qualified Prelude
+import           System.IO                     (Handle)
+import qualified System.IO
+
+-- | Data which can be read to and from files and handles.
+--
+-- Note that, for lazy sequences, these operations may perform
+-- lazy I\/O.
+class IsSequence a => IOData a where
+    readFile     :: MonadIO m => FilePath -> m a
+    writeFile    :: MonadIO m => FilePath -> a -> m ()
+    getLine      :: MonadIO m => m a
+    hGetContents :: MonadIO m => Handle -> m a
+    hGetLine     :: MonadIO m => Handle -> m a
+    hPut         :: MonadIO m => Handle -> a -> m ()
+    hPutStrLn    :: MonadIO m => Handle -> a -> m ()
+    hGetChunk    :: MonadIO m => Handle -> m a
+instance IOData ByteString.ByteString where
+    readFile = liftIO . ByteString.readFile . FilePath.encodeString
+    writeFile fp = liftIO . ByteString.writeFile (FilePath.encodeString fp)
+    getLine = liftIO ByteString.getLine
+    hGetContents = liftIO . ByteString.hGetContents
+    hGetLine = liftIO . ByteString.hGetLine
+    hPut h = liftIO . ByteString.hPut h
+    hPutStrLn h = liftIO . ByteString8.hPutStrLn h
+    hGetChunk = liftIO . flip ByteString.hGetSome defaultChunkSize
+instance IOData LByteString.ByteString where
+    readFile = liftIO . LByteString.readFile . FilePath.encodeString
+    writeFile fp = liftIO . LByteString.writeFile (FilePath.encodeString fp)
+    getLine = liftM fromStrict (liftIO ByteString.getLine)
+    hGetContents = liftIO . LByteString.hGetContents
+    hGetLine = liftM fromStrict . liftIO . ByteString.hGetLine
+    hPut h = liftIO . LByteString.hPut h
+    hPutStrLn h lbs = liftIO $ do
+        LByteString.hPutStr h lbs
+        ByteString8.hPutStrLn h ByteString.empty
+    hGetChunk = liftM fromStrict . hGetChunk
+instance IOData Text.Text where
+    readFile = liftIO . Text.readFile . FilePath.encodeString
+    writeFile fp = liftIO . Text.writeFile (FilePath.encodeString fp)
+    getLine = liftIO Text.getLine
+    hGetContents = liftIO . Text.hGetContents
+    hGetLine = liftIO . Text.hGetLine
+    hPut h = liftIO . Text.hPutStr h
+    hPutStrLn h = liftIO . Text.hPutStrLn h
+#if MIN_VERSION_text(0, 11, 3)
+    hGetChunk = liftIO . Text.hGetChunk
+#else
+    -- Dangerously inefficient!
+    hGetChunk = liftIO . liftM Text.singleton . System.IO.hGetChar
+#endif
+instance IOData LText.Text where
+    readFile = liftIO . LText.readFile . FilePath.encodeString
+    writeFile fp = liftIO . LText.writeFile (FilePath.encodeString fp)
+    getLine = liftIO LText.getLine
+    hGetContents = liftIO . LText.hGetContents
+    hGetLine = liftIO . LText.hGetLine
+    hPut h = liftIO . LText.hPutStr h
+    hPutStrLn h = liftIO . LText.hPutStrLn h
+    hGetChunk = liftM fromStrict . hGetChunk
+instance (Char ~ c) => IOData [c] where
+    readFile = liftIO . Prelude.readFile . FilePath.encodeString
+    writeFile fp = liftIO . Prelude.writeFile (FilePath.encodeString fp)
+    getLine = liftIO Prelude.getLine
+    hGetContents = liftIO . System.IO.hGetContents
+    hGetLine = liftIO . System.IO.hGetLine
+    hPut h = liftIO . System.IO.hPutStr h
+    hPutStrLn h = liftIO . System.IO.hPutStrLn h
+    hGetChunk = liftM Text.unpack . hGetChunk
diff --git a/Data/Sequences/Lazy.hs b/Data/Sequences/Lazy.hs
new file mode 100644
--- /dev/null
+++ b/Data/Sequences/Lazy.hs
@@ -0,0 +1,28 @@
+{-# LANGUAGE FunctionalDependencies #-}
+{-# LANGUAGE MultiParamTypeClasses  #-}
+module Data.Sequences.Lazy where
+
+import qualified Data.ByteString      as S
+import qualified Data.ByteString.Lazy as L
+import           Data.Sequences
+import qualified Data.Text            as T
+import qualified Data.Text.Lazy       as TL
+
+-- | Lazy sequences containing strict chunks of data.
+class (IsSequence lazy, IsSequence strict) => LazySequence lazy strict | lazy -> strict, strict -> lazy where
+    toChunks :: lazy -> [strict]
+    fromChunks :: [strict] -> lazy
+    toStrict :: lazy -> strict
+    fromStrict :: strict -> lazy
+
+instance LazySequence L.ByteString S.ByteString where
+    toChunks = L.toChunks
+    fromChunks = L.fromChunks
+    toStrict = S.concat . L.toChunks
+    fromStrict = L.fromChunks . return
+
+instance LazySequence TL.Text T.Text where
+    toChunks = TL.toChunks
+    fromChunks = TL.fromChunks
+    toStrict = TL.toStrict
+    fromStrict = TL.fromStrict
diff --git a/Data/Textual/Encoding.hs b/Data/Textual/Encoding.hs
new file mode 100644
--- /dev/null
+++ b/Data/Textual/Encoding.hs
@@ -0,0 +1,31 @@
+{-# LANGUAGE FunctionalDependencies #-}
+{-# LANGUAGE MultiParamTypeClasses  #-}
+{-# LANGUAGE TypeFamilies           #-}
+{-# LANGUAGE UndecidableInstances   #-}
+module Data.Textual.Encoding where
+
+import qualified Data.ByteString          as S
+import qualified Data.ByteString.Lazy     as L
+import           Data.Sequences
+import qualified Data.Text                as T
+import qualified Data.Text.Encoding       as T
+import           Data.Text.Encoding.Error (lenientDecode)
+import qualified Data.Text.Lazy           as TL
+import qualified Data.Text.Lazy.Encoding  as TL
+import           Data.Word                (Word8)
+
+-- | Textual data which can be encoded to and decoded from UTF8.
+class (Textual textual, IsSequence binary) => Utf8 textual binary | textual -> binary, binary -> textual where
+    encodeUtf8 :: textual -> binary
+    -- | Note that this function is required to be pure. In the case of
+    -- a decoding error, Unicode replacement characters must be used.
+    decodeUtf8 :: binary -> textual
+instance (c ~ Char, w ~ Word8) => Utf8 [c] [w] where
+    encodeUtf8 = L.unpack . TL.encodeUtf8 . TL.pack
+    decodeUtf8 = TL.unpack . TL.decodeUtf8With lenientDecode . L.pack
+instance Utf8 T.Text S.ByteString where
+    encodeUtf8 = T.encodeUtf8
+    decodeUtf8 = T.decodeUtf8With lenientDecode
+instance Utf8 TL.Text L.ByteString where
+    encodeUtf8 = TL.encodeUtf8
+    decodeUtf8 = TL.decodeUtf8With lenientDecode
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,20 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 FP Complete
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/chunked-data.cabal b/chunked-data.cabal
new file mode 100644
--- /dev/null
+++ b/chunked-data.cabal
@@ -0,0 +1,29 @@
+name:                chunked-data
+version:             0.1.0.0
+synopsis:            Typeclasses for dealing with various chunked data representations
+description:         Originally present in classy-prelude.
+homepage:            https://github.com/fpco/chunked-data
+license:             MIT
+license-file:        LICENSE
+author:              Michael Snoyman
+maintainer:          michael@snoyman.com
+category:            Data
+build-type:          Simple
+cabal-version:       >=1.8
+
+library
+  exposed-modules:     Data.IOData
+                       Data.Textual.Encoding
+                       Data.Sequences.Lazy
+                       Data.Builder
+                       Data.ChunkedZip
+  build-depends:       base >= 4 && < 5
+                     , transformers
+                     , bytestring
+                     , mono-traversable >=0.2
+                     , text >= 0.11
+                     , system-filepath
+                     , blaze-builder
+                     , containers
+                     , vector
+                     , semigroups
