diff --git a/COPYING b/COPYING
new file mode 100644
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,29 @@
+Copyright (c) 2008, Taru Karttunen
+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 the Taru Karttunen; nor the names of its 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/Data/Hex.hs b/Data/Hex.hs
new file mode 100644
--- /dev/null
+++ b/Data/Hex.hs
@@ -0,0 +1,72 @@
+{-# LANGUAGE TypeSynonymInstances #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Data.Hex
+-- Copyright   :  (c) Taru Karttunen 2009
+-- License     :  BSD-style
+-- Maintainer  :  taruti@taruti.net
+-- Stability   :  provisional
+-- Portability :  portable
+--
+-- Convert strings into hexadecimal and back.
+--
+-----------------------------------------------------------------------------
+module Data.Hex where
+
+import Control.Monad
+import qualified Data.ByteString.Char8 as B
+import qualified Data.ByteString.Lazy.Char8 as L
+
+-- | Convert strings into hexadecimal and back.
+class Hex t where
+    -- | Convert string into hexadecimal.
+    hex   :: t -> t
+    -- | Convert from hexadecimal and fail on invalid input.
+    unhex :: Monad m => t -> m t
+
+
+instance Hex String where
+    hex = Prelude.concatMap w
+        where w ch = let s = "0123456789ABCDEF"
+                         x = fromEnum ch
+                     in [s !! div x 16,s !! mod x 16]
+    unhex []      = return []
+    unhex (a:b:r) = do x <- c a
+                       y <- c b
+                       liftM (toEnum ((x * 16) + y) :) $ unhex r
+    unhex [_]      = fail "Non-even length"
+
+
+c :: Monad m => Char -> m Int
+c '0' = return 0
+c '1' = return 1
+c '2' = return 2
+c '3' = return 3
+c '4' = return 4
+c '5' = return 5
+c '6' = return 6
+c '7' = return 7
+c '8' = return 8
+c '9' = return 9
+c 'A' = return 10
+c 'B' = return 11
+c 'C' = return 12
+c 'D' = return 13
+c 'E' = return 14
+c 'F' = return 15
+c 'a' = return 10
+c 'b' = return 11
+c 'c' = return 12
+c 'd' = return 13
+c 'e' = return 14
+c 'f' = return 15
+c _   = fail "Invalid hex digit!"
+
+instance Hex B.ByteString where
+    hex = B.pack . hex . B.unpack
+    unhex x = liftM B.pack $ unhex $ B.unpack x
+
+instance Hex L.ByteString where
+    hex = L.pack . hex . L.unpack
+    unhex x = liftM L.pack $ unhex $ L.unpack x
+
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,3 @@
+#!/usr/bin/env runhaskell
+import Distribution.Simple
+main = defaultMain
diff --git a/hex.cabal b/hex.cabal
new file mode 100644
--- /dev/null
+++ b/hex.cabal
@@ -0,0 +1,15 @@
+Name:                hex
+Version:             0.1
+Synopsis:            Convert strings into hexadecimal and back.
+Description:         Convert strings into hexadecimal and back.
+License:             BSD3
+License-file:        COPYING
+Copyright:           Taru Karttunen <taruti@taruti.net>
+Author:              Taru Karttunen
+Category:            Data
+Maintainer:          taruti@taruti.net
+Build-Depends:       base>3, bytestring
+Exposed-modules:     Data.Hex
+Extensions:          TypeSynonymInstances
+GHC-Options:         -Wall
+Build-Type:	     Simple
