diff --git a/Data/Syntax/Printer/ByteString.hs b/Data/Syntax/Printer/ByteString.hs
new file mode 100644
--- /dev/null
+++ b/Data/Syntax/Printer/ByteString.hs
@@ -0,0 +1,43 @@
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{- |
+Module      :  Data.Syntax.Printer.ByteString
+Description :  Prints to a ByteString Builder using strict ByteString as the sequence.
+Copyright   :  (c) Paweł Nowak
+License     :  MIT
+
+Maintainer  :  Paweł Nowak <pawel834@gmail.com>
+Stability   :  experimental
+-}
+module Data.Syntax.Printer.ByteString (
+    Printer,
+    runPrinter
+    )
+    where
+
+import           Control.Monad
+import           Data.ByteString (ByteString)
+import qualified Data.ByteString as BS
+import           Data.ByteString.Lazy.Builder
+import           Data.SemiIsoFunctor
+import           Data.Syntax
+import           Data.Syntax.Printer.Consumer
+
+-- | Prints a value to a Text Builder using a syntax description.
+newtype Printer a = Printer { getConsumer :: Consumer Builder a }
+    deriving (SemiIsoFunctor, SemiIsoApply, SemiIsoAlternative, SemiIsoMonad)
+
+instance Syntax Printer ByteString where
+    anyChar = Printer . Consumer $ Right . word8
+    take n = Printer . Consumer $ Right . byteString . BS.take n
+    takeWhile p = Printer . Consumer $ Right . byteString . BS.takeWhile p
+    takeWhile1 p = Printer . Consumer $ Right . byteString <=< notNull . BS.takeWhile p
+      where notNull t | BS.null t  = Left "takeWhile1 failed"
+                      | otherwise = Right t
+    takeTill1 p = Printer . Consumer $ Right . byteString <=< notNull . BS.takeWhile (not . p)
+      where notNull t | BS.null t  = Left "takeTill1 failed"
+                      | otherwise = Right t
+
+-- | Runs the printer.
+runPrinter :: Printer a -> a -> Either String Builder
+runPrinter = runConsumer . getConsumer
diff --git a/Data/Syntax/Printer/ByteString/Lazy.hs b/Data/Syntax/Printer/ByteString/Lazy.hs
new file mode 100644
--- /dev/null
+++ b/Data/Syntax/Printer/ByteString/Lazy.hs
@@ -0,0 +1,43 @@
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{- |
+Module      :  Data.Syntax.Printer.ByteString.Lazy
+Description :  Prints to a ByteString Builder using lazy ByteString as the sequence.
+Copyright   :  (c) Paweł Nowak
+License     :  MIT
+
+Maintainer  :  Paweł Nowak <pawel834@gmail.com>
+Stability   :  experimental
+-}
+module Data.Syntax.Printer.ByteString.Lazy (
+    Printer,
+    runPrinter
+    )
+    where
+
+import           Control.Monad
+import           Data.ByteString.Lazy (ByteString)
+import qualified Data.ByteString.Lazy as BS
+import           Data.ByteString.Lazy.Builder
+import           Data.SemiIsoFunctor
+import           Data.Syntax
+import           Data.Syntax.Printer.Consumer
+
+-- | Prints a value to a Text Builder using a syntax description.
+newtype Printer a = Printer { getConsumer :: Consumer Builder a }
+    deriving (SemiIsoFunctor, SemiIsoApply, SemiIsoAlternative, SemiIsoMonad)
+
+instance Syntax Printer ByteString where
+    anyChar = Printer . Consumer $ Right . word8
+    take n = Printer . Consumer $ Right . lazyByteString . BS.take (fromIntegral n)
+    takeWhile p = Printer . Consumer $ Right . lazyByteString . BS.takeWhile p
+    takeWhile1 p = Printer . Consumer $ Right . lazyByteString <=< notNull . BS.takeWhile p
+      where notNull t | BS.null t  = Left "takeWhile1 failed"
+                      | otherwise = Right t
+    takeTill1 p = Printer . Consumer $ Right . lazyByteString <=< notNull . BS.takeWhile (not . p)
+      where notNull t | BS.null t  = Left "takeTill1 failed"
+                      | otherwise = Right t
+
+-- | Runs the printer.
+runPrinter :: Printer a -> a -> Either String Builder
+runPrinter = runConsumer . getConsumer
diff --git a/Data/Syntax/Printer/Consumer.hs b/Data/Syntax/Printer/Consumer.hs
new file mode 100644
--- /dev/null
+++ b/Data/Syntax/Printer/Consumer.hs
@@ -0,0 +1,33 @@
+{- |
+Module      :  Data.Syntax.Printer.Consumer
+Description :  Common base for both Text and ByteString printers.
+Copyright   :  (c) Paweł Nowak
+License     :  MIT
+
+Maintainer  :  Paweł Nowak <pawel834@gmail.com>
+Stability   :  experimental
+-}
+module Data.Syntax.Printer.Consumer where
+
+import Control.Applicative
+import Control.Lens.SemiIso
+import Control.Monad
+import Data.Monoid
+import Data.SemiIsoFunctor
+
+-- | A contravariant functor that consumes values using a monoid.
+newtype Consumer m a = Consumer { runConsumer :: a -> Either String m }
+
+instance SemiIsoFunctor (Consumer m) where
+    simap f (Consumer p) = Consumer $ apply f >=> p
+
+instance Monoid m => SemiIsoApply (Consumer m) where
+    siunit = Consumer $ \_ -> Right mempty
+    Consumer f /*/ Consumer g = Consumer $ \(a, b) -> (<>) <$> f a <*> g b
+
+instance Monoid m => SemiIsoAlternative (Consumer m) where
+    siempty = Consumer $ \_ -> Left "siempty"
+    Consumer f /|/ Consumer g = Consumer $ \a -> f a <|> g a
+
+instance Monoid m => SemiIsoMonad (Consumer m) where
+    Consumer m //= f = Consumer $ \(a, b) -> (<>) <$> m a <*> runConsumer (f a) b
diff --git a/Data/Syntax/Printer/Text.hs b/Data/Syntax/Printer/Text.hs
new file mode 100644
--- /dev/null
+++ b/Data/Syntax/Printer/Text.hs
@@ -0,0 +1,53 @@
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{- |
+Module      :  Data.Syntax.Printer.Text
+Description :  Prints to a Text Builder using strict Text as the sequence.
+Copyright   :  (c) Paweł Nowak
+License     :  MIT
+
+Maintainer  :  Paweł Nowak <pawel834@gmail.com>
+Stability   :  experimental
+-}
+module Data.Syntax.Printer.Text (
+    Printer,
+    runPrinter
+    )
+    where
+
+import           Control.Monad
+import           Data.SemiIsoFunctor
+import           Data.Syntax
+import           Data.Syntax.Char
+import           Data.Syntax.Printer.Consumer
+import           Data.Text (Text)
+import qualified Data.Text as T
+import           Data.Text.Lazy.Builder
+import qualified Data.Text.Lazy.Builder.Int as B
+import qualified Data.Text.Lazy.Builder.RealFloat as B
+import qualified Data.Text.Lazy.Builder.Scientific as B
+
+-- | Prints a value to a Text Builder using a syntax description.
+newtype Printer a = Printer { getConsumer :: Consumer Builder a }
+    deriving (SemiIsoFunctor, SemiIsoApply, SemiIsoAlternative, SemiIsoMonad)
+
+instance Syntax Printer Text where
+    anyChar = Printer . Consumer $ Right . singleton
+    take n = Printer . Consumer $ Right . fromText . T.take n
+    takeWhile p = Printer . Consumer $ Right . fromText . T.takeWhile p
+    takeWhile1 p = Printer . Consumer $ Right . fromText <=< notNull . T.takeWhile p
+      where notNull t | T.null t  = Left "takeWhile1 failed"
+                      | otherwise = Right t
+    takeTill1 p = Printer . Consumer $ Right . fromText <=< notNull . T.takeWhile (not . p)
+      where notNull t | T.null t  = Left "takeTill1 failed"
+                      | otherwise = Right t
+
+instance SyntaxChar Printer Text where
+    decimal = Printer . Consumer $ Right . B.decimal
+    hexadecimal = Printer . Consumer $ Right . B.hexadecimal
+    realFloat = Printer . Consumer $ Right . B.realFloat
+    scientific = Printer . Consumer $ Right . B.scientificBuilder
+
+-- | Runs the printer.
+runPrinter :: Printer a -> a -> Either String Builder
+runPrinter = runConsumer . getConsumer
diff --git a/Data/Syntax/Printer/Text/Lazy.hs b/Data/Syntax/Printer/Text/Lazy.hs
new file mode 100644
--- /dev/null
+++ b/Data/Syntax/Printer/Text/Lazy.hs
@@ -0,0 +1,53 @@
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{- |
+Module      :  Data.Syntax.Printer.Text.Lazy
+Description :  Prints to a Text Builder using lazy Text as the sequence.
+Copyright   :  (c) Paweł Nowak
+License     :  MIT
+
+Maintainer  :  Paweł Nowak <pawel834@gmail.com>
+Stability   :  experimental
+-}
+module Data.Syntax.Printer.Text.Lazy (
+    Printer,
+    runPrinter
+    )
+    where
+
+import           Control.Monad
+import           Data.SemiIsoFunctor
+import           Data.Syntax
+import           Data.Syntax.Char
+import           Data.Syntax.Printer.Consumer
+import           Data.Text.Lazy (Text)
+import qualified Data.Text.Lazy as T
+import           Data.Text.Lazy.Builder
+import qualified Data.Text.Lazy.Builder.Int as B
+import qualified Data.Text.Lazy.Builder.RealFloat as B
+import qualified Data.Text.Lazy.Builder.Scientific as B
+
+-- | Prints a value to a Text Builder using a syntax description.
+newtype Printer a = Printer { getConsumer :: Consumer Builder a }
+    deriving (SemiIsoFunctor, SemiIsoApply, SemiIsoAlternative, SemiIsoMonad)
+
+instance Syntax Printer Text where
+    anyChar = Printer . Consumer $ Right . singleton
+    take n = Printer . Consumer $ Right . fromLazyText . T.take (fromIntegral n)
+    takeWhile p = Printer . Consumer $ Right . fromLazyText . T.takeWhile p
+    takeWhile1 p = Printer . Consumer $ Right . fromLazyText <=< notNull . T.takeWhile p
+      where notNull t | T.null t  = Left "takeWhile1 failed"
+                      | otherwise = Right t
+    takeTill1 p = Printer . Consumer $ Right . fromLazyText <=< notNull . T.takeWhile (not . p)
+      where notNull t | T.null t  = Left "takeTill1 failed"
+                      | otherwise = Right t
+
+instance SyntaxChar Printer Text where
+    decimal = Printer . Consumer $ Right . B.decimal
+    hexadecimal = Printer . Consumer $ Right . B.hexadecimal
+    realFloat = Printer . Consumer $ Right . B.realFloat
+    scientific = Printer . Consumer $ Right . B.scientificBuilder
+
+-- | Runs the printer.
+runPrinter :: Printer a -> a -> Either String Builder
+runPrinter = runConsumer . getConsumer
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2014 Paweł Nowak
+
+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/syntax-printer.cabal b/syntax-printer.cabal
new file mode 100644
--- /dev/null
+++ b/syntax-printer.cabal
@@ -0,0 +1,21 @@
+name:                syntax-printer
+version:             0.1.0.0
+synopsis:            Text and ByteString printers for 'syntax'.
+license:             MIT
+license-file:        LICENSE
+author:              Paweł Nowak
+maintainer:          Paweł Nowak <pawel834@gmail.com>
+copyright:           Paweł Nowak 2014
+category:            Data
+build-type:          Simple
+cabal-version:       >=1.10
+
+library
+  exposed-modules:     Data.Syntax.Printer.Consumer
+                       Data.Syntax.Printer.Text
+                       Data.Syntax.Printer.Text.Lazy
+                       Data.Syntax.Printer.ByteString
+                       Data.Syntax.Printer.ByteString.Lazy
+  build-depends:       base >=4.7 && <4.8, semi-iso >= 0.5, syntax >= 0.3, text, bytestring, scientific >= 0.3
+  default-language:    Haskell2010
+  ghc-options:         -Wall
