diff --git a/Data/String/Combinators.hs b/Data/String/Combinators.hs
new file mode 100644
--- /dev/null
+++ b/Data/String/Combinators.hs
@@ -0,0 +1,251 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Data.String.Combinators
+-- Copyright   :  (c) 2009 Bas van Dijk
+-- License     :  BSD-style (see the file LICENSE)
+--
+-- Maintainer  :  Bas van Dijk <v.dijk.bas@gmail.com>
+-- Stability   :  Stable
+-- Portability :  Requires OverloadedStrings
+--
+-- Note that I am thinking about putting some of the combinators
+-- (('<>'), ('<+>'), ('$$') and maybe more) in a type class. This
+-- allows the \'pretty\' package to use this package.
+--
+-----------------------------------------------------------------------------
+
+module Data.String.Combinators
+    (
+      -- * Combining
+      (<>)
+    , mid
+    , (<+>)
+    , ($$)
+    , hcat
+    , hsep
+    , vcat
+    , punctuate
+
+     -- * Wrapping in delimiters
+    , between
+
+    , paren
+    , brackets
+    , braces
+    , angleBrackets
+    , quotes
+    , doubleQuotes
+
+      -- * From characters
+    , char
+
+    , semi
+    , colon
+    , comma
+    , space
+    , newline
+    , equals
+    , lparen
+    , rparen
+    , lbrack
+    , rbrack
+    , lbrace
+    , rbrace
+    , labrack
+    , rabrack
+
+      -- * From showable values
+    , fromShow
+
+    , int
+    , integer
+    , float
+    , double
+    , rational
+
+    )
+    where
+
+
+import Data.String
+import Data.Monoid
+
+
+----------------------------------------------------------------------
+-- Combining
+----------------------------------------------------------------------
+
+-- | Put two strings besides eachother.
+-- Note that '<>' is just a synonym for 'mappend'.
+(<>) :: Monoid s => s -> s -> s
+(<>) = mappend
+
+-- | @mid m x y@ Puts @x@ and @y@ around @m@.
+-- Note that: @mid m x y =@ 'between' @x y m@
+mid :: Monoid s => s -> (s -> s -> s)
+mid m x y = between x y m
+
+-- | Put two strings besides eachother separated by a space.
+(<+>) :: (Monoid s, IsString s) => s -> s -> s
+(<+>) = mid space
+
+-- | Put two strings above eachother.
+($$) :: (Monoid s, IsString s) => s -> s -> s
+($$) = mid newline
+
+infixl 6 <>
+infixl 6 <+>
+infixl 5 $$
+
+-- | List version of '<>'
+hcat :: Monoid s => [s] -> s
+hcat = foldr (<>) mempty
+
+-- | List version of '<+>'
+hsep :: (Monoid s, IsString s) => [s] -> s
+hsep = foldr (<+>) mempty
+
+-- | List version of '$$'
+vcat :: (Monoid s, IsString s) =>  [s] -> s
+vcat = foldr ($$) mempty
+
+-- | @punctuate p [d1, ... dn] = [d1 \<> p, d2 \<> p, ... dn-1 \<> p, dn]@
+
+-- Shamelessly copied from 'pretty':
+punctuate :: (Monoid s) => s -> [s] -> [s]
+punctuate _ []     = []
+punctuate p (d:ds) = go d ds
+    where
+      go d' []     = [d']
+      go d' (e:es) = (d' <> p) : go e es
+
+
+----------------------------------------------------------------------
+-- Wrapping in delimiters
+----------------------------------------------------------------------
+
+-- | @between b c s@ wraps the string @s@ between @b@ and @c@
+between :: (Monoid s) => s -> s -> (s -> s)
+between open close x = open <> x <> close
+
+
+-- | wrap a string in @(...)@
+paren :: (Monoid s, IsString s) => s -> s
+paren = between "(" ")"
+
+-- | wrap a string in @[...]@
+brackets :: (Monoid s, IsString s) => s -> s
+brackets = between "[" "]"
+
+-- | wrap a string in @{...}@
+braces :: (Monoid s, IsString s) => s -> s
+braces = between "{" "}"
+
+-- | wrap a string in @\<...\>@
+angleBrackets :: (Monoid s, IsString s) => s -> s
+angleBrackets = between "<" ">"
+
+-- | wrap a string in @\'...\'@
+quotes :: (Monoid s, IsString s) => s -> s
+quotes = between "'" "'"
+
+-- | wrap a string in @\"...\"@
+doubleQuotes :: (Monoid s, IsString s) => s -> s
+doubleQuotes = between "\"" "\""
+
+
+----------------------------------------------------------------------
+-- From characters
+----------------------------------------------------------------------
+
+-- | convert a character to a string
+char :: IsString s => Char -> s
+char c = fromString [c]
+
+
+-- | A ';' character
+semi :: IsString s => s
+semi = char ';'
+
+-- | A ':' character
+colon :: IsString s => s
+colon = char ':'
+
+-- | A ',' character
+comma :: IsString s => s
+comma = char ','
+
+-- | A ' ' character
+space :: IsString s => s
+space = char ' '
+
+-- | A '\n' character
+newline :: IsString s => s
+newline = char '\n'
+
+-- | A '=' character
+equals :: IsString s => s
+equals = char '='
+
+-- | A '(' character
+lparen :: IsString s => s
+lparen = char '('
+
+-- | A ')' character
+rparen :: IsString s => s
+rparen = char ')'
+
+-- | A '[' character
+lbrack :: IsString s => s
+lbrack = char '['
+
+-- | A ']' character
+rbrack :: IsString s => s
+rbrack = char ']'
+
+-- | A '{' character
+lbrace :: IsString s => s
+lbrace = char '{'
+
+-- | A '}' character
+rbrace :: IsString s => s
+rbrace = char '}'
+
+-- | A \'<\' character
+labrack :: IsString s => s
+labrack = char '<'
+
+-- | A \'>\' character
+rabrack :: IsString s => s
+rabrack = char '>'
+
+
+----------------------------------------------------------------------
+-- From showable values
+----------------------------------------------------------------------
+
+-- | Convert a Show-able value to a string.
+-- @fromShow = fromString . show@
+fromShow :: (Show a, IsString s) => a -> s
+fromShow = fromString . show
+
+
+int :: IsString s => Int -> s
+int = fromShow
+
+integer :: IsString s => Integer -> s
+integer = fromShow
+
+float :: IsString s => Float -> s
+float = fromShow
+
+double :: IsString s => Double -> s
+double = fromShow
+
+rational :: IsString s => Rational -> s
+rational = fromShow
+
+
+-- The End -----------------------------------------------------------
diff --git a/Data/String/Stringable.hs b/Data/String/Stringable.hs
new file mode 100644
--- /dev/null
+++ b/Data/String/Stringable.hs
@@ -0,0 +1,54 @@
+{-# LANGUAGE TypeSynonymInstances #-}
+
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Data.String.Stringable
+-- Copyright   :  (c) 2009 Bas van Dijk
+-- License     :  BSD-style (see the file LICENSE)
+--
+-- Maintainer  :  Bas van Dijk <v.dijk.bas@gmail.com>
+-- Stability   :  Stable
+-- Portability :  Requires TypeSynonymInstances
+--
+-----------------------------------------------------------------------------
+
+module Data.String.Stringable (Stringable(..)) where
+
+
+import Data.String
+
+import qualified Data.ByteString.Char8 as B
+import qualified Data.DString          as DS
+import qualified Data.Text             as T
+import qualified Text.PrettyPrint      as PP
+
+
+-- | Class of types that can be converted to and from a String.
+class IsString s => Stringable s where
+    toString :: s -> String
+
+
+instance Stringable String where
+    toString = id
+
+instance Stringable B.ByteString where
+    toString = B.unpack
+
+instance Stringable PP.Doc where
+    toString = PP.render
+
+instance Stringable ShowS where
+    toString s = s []
+
+instance Stringable DS.DString where
+    toString = DS.toString
+
+instance Stringable T.Text where
+    toString = T.unpack
+
+
+instance IsString ShowS where
+    fromString = showString
+
+instance IsString PP.Doc where
+    fromString = PP.text
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2009, Bas van Dijk
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Bas van Dijk nor the names of his
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Setup.lhs b/Setup.lhs
new file mode 100644
--- /dev/null
+++ b/Setup.lhs
@@ -0,0 +1,4 @@
+#! /usr/bin/env runhaskell
+ 
+> import Distribution.Simple
+> main = defaultMain
diff --git a/string-combinators.cabal b/string-combinators.cabal
new file mode 100644
--- /dev/null
+++ b/string-combinators.cabal
@@ -0,0 +1,36 @@
+Name:                   string-combinators
+Version:                0.1
+Synopsis:               Polymorphic functions to build and combine stringlike values
+Description:            string-combinators provides handy polymorphic functions
+                        to build and combine stringlike values.
+                        .
+                        All functions are polymorphic in their string type
+                        but usually have a Monoid or IsString constraint.
+                        .
+                        Conditionally a module Data.String.Stringable is provided.
+                        This module exports a typeclass Stringable
+                        for converting values to and from Strings.
+                        A bunch of instances is defined
+                        for some common stringlike types.
+Category:               Data
+License:                BSD3
+License-file:           LICENSE
+Author:                 Bas van Dijk <v.dijk.bas@gmail.com>
+Maintainer:             Bas van Dijk <v.dijk.bas@gmail.com>
+Copyright:              2009 Bas van Dijk <v.dijk.bas@gmail.com>
+Cabal-version:          >= 1.2
+Build-Type:             Simple
+Stability:              experimental
+
+Flag Stringable
+  Description: Include the Data.String.Stringable module
+
+Library
+  Build-Depends:        base
+  Exposed-modules:      Data.String.Combinators
+
+  if flag(Stringable)
+    Build-Depends:      bytestring, dstring, text, pretty
+    Exposed-modules:    Data.String.Stringable
+
+  Ghc-options:          -O2 -Wall
