diff --git a/Dish.cabal b/Dish.cabal
--- a/Dish.cabal
+++ b/Dish.cabal
@@ -1,5 +1,5 @@
 name:                Dish
-version:             0.0.0.4
+version:             0.0.0.5
 homepage:            http://github.com/zcourts/Dish
 license:             BSD3
 license-file:        LICENSE
@@ -22,11 +22,21 @@
   build-depends:    
                     base >=4.6.0 && <4.7,
                     bytestring >=0.10.0 && <0.11
-  hs-source-dirs:   src
+  hs-source-dirs:   src, examples
   c-sources:        cbits/murmur3.c
   include-dirs:     cbits
-  extra-libraries:   
-  --cc-options:       -O3
+  extra-libraries:    
   extensions:       ForeignFunctionInterface
-  other-modules:    
+  other-modules:      
   exposed-modules:  Data.Dish.Murmur3
+
+executable Dish
+  build-depends:   base >= 4,
+                   bytestring >=0.10.0 && <0.11,
+                   Dish >= 0.0.0.5
+  hs-source-dirs:  examples
+  ghc-options:     -Wall -rtsopts
+  c-sources:        cbits/murmur3.c
+  include-dirs:     cbits
+  main-is:         Main.hs
+
diff --git a/examples/Main.hs b/examples/Main.hs
new file mode 100644
--- /dev/null
+++ b/examples/Main.hs
@@ -0,0 +1,28 @@
+module Main where
+import Data.Dish.Murmur3
+import qualified Data.ByteString.Char8 as B
+
+main :: IO ()
+main = do   let val = Str "abc 123"
+            let valByteString = B.pack $ strCon val
+            print $ murmur3Int val 42
+            print $ murmur3IntegerX86 val 42
+            print $ murmur3IntegerX64 valByteString 42
+            --
+            d <- murmur3Raw  valByteString 42 X86_32
+            print d
+            e <- murmur3Raw  val 42 X86_128
+            print e
+            f <- murmur3Raw  val 42 X64_128
+            print f
+            --
+            print $ murmur3 val 42 X86_32
+            print $ murmur3 valByteString 42 X86_128
+            print $ murmur3 val 42 X64_128
+            --
+            j <- murmur3Int' val 42
+            print j
+            k <- murmur3IntegerX86' val 42
+            print k
+            l <- murmur3IntegerX64' valByteString 42
+            print l
diff --git a/src/Data/Dish/Murmur3.hs b/src/Data/Dish/Murmur3.hs
--- a/src/Data/Dish/Murmur3.hs
+++ b/src/Data/Dish/Murmur3.hs
@@ -9,6 +9,12 @@
 and about the speed of unaligned reads. 
 -} 
 module Data.Dish.Murmur3(
+                         -- * Murmur3 Hash Version
+                         MHV(..),
+                         -- * Hashable
+                         -- If a value can be represented as a 'CString' then it can be hashed
+                         Murmur3Hashable(..),
+                         Str(..),
                          -- * Default/Direct Map
                          -- $default
                          murmur3,
@@ -26,32 +32,44 @@
                          murmur3IntegerX64,
                          murmur3IntegerX64',
                          -- * FFI
-                         murmur3Raw,
-                         -- * Murmur3 Hash Version
-                         MHV(..)
+                         murmur3Raw
                          ) where
 import Foreign.C
 import Foreign.Ptr
 import Foreign
 import qualified Data.List as L
-import qualified Data.Bits as B
+import qualified Data.Bits as BITS
 import qualified System.IO.Unsafe as US
+import qualified Data.ByteString as B
 
 -- Murmur Hash version, one of 
 data MHV = X86_32 | X86_128 | X64_128
 
+--http://www.haskell.org/haskellwiki/List_instance
+-- | Because String isn't a \'real\' type :(
+newtype Str = Str{ strCon :: String }
 
+-- | Provides an interface for any value which is capable of being represented as a 'CString'
+class Murmur3Hashable a where
+  toCstring :: a -> IO CStringLen
+    
+instance Murmur3Hashable Str where
+  toCstring val = withCAStringLen (strCon val) $ \x -> return x
+    
+instance Murmur3Hashable B.ByteString where
+  toCstring val = B.useAsCStringLen val $ \x -> return x     
+  
 {-$default 
 Simple, verbose interface for generating hashes
 -}
 -- | Base function, which allows you to choose which 'MHV' to use        
-murmur3 :: String   -- ^ The string to be hashed
+murmur3 :: Murmur3Hashable a => a   -- ^ The hashable to be hashed
            -> Int   -- ^ A seed value for the hash function
            -> MHV   -- ^ Which Murmur Hash version to use 'X86_32', 'X86_128' or 'X64_128'
            -> [Int] -- ^ returns 4, 32 bit ints, if 'X86_32' is used only the first has a value and the other 3 are 0
 murmur3 v s ver = US.unsafePerformIO $ murmur3' v s ver
 
-murmur3' :: String     -- ^ The string to be hashed
+murmur3' :: Murmur3Hashable a => a     -- ^ The hashable to be hashed
            -> Int      -- ^ A seed value for the hash function
            -> MHV      -- ^ Which Murmur Hash version to use 'X86_32', 'X86_128' or 'X64_128'
            -> IO [Int] -- ^ returns 4, 32 bit ints, if 'X86_32' is used only the first has a value and the other 3 are 0
@@ -68,9 +86,9 @@
 {-$32
 Generate 32 bit hash values
 -}                    
-murmur3Int' :: String -- ^ The string to be hashed
+murmur3Int' :: Murmur3Hashable a => a -- ^ The hashable to be hashed
                      -> Int -- ^ A seed value for the hash function
-                     -> IO Int -- ^ 32 bit number generated from the string
+                     -> IO Int -- ^ 32 bit number generated from the hashable
 murmur3Int' val seed = do v <- murmur3Raw val seed X86_32 
                          -- safe to use L.head, list is never empty even if all vals are 0
                           return $ fromIntegral (L.head v)
@@ -78,18 +96,18 @@
 {- | has the lowest throughput, but also the lowest latency. If you're making a 
 hash table that usually has small keys, this is probably the one you want to use 
 on 32-bit machines. It has a 32-bit output. -}    
-murmur3Int :: String -- ^ The string to be hashed
+murmur3Int :: Murmur3Hashable a => a -- ^ The hashable to be hashed
                      -> Int -- ^ A seed value for the hash function
-                     -> Int -- ^ 32 bit number generated from the string
+                     -> Int -- ^ 32 bit number generated from the hashable
 murmur3Int val seed = US.unsafePerformIO $ murmur3Int' val seed
 
 
 {-$x128
 Generate 128 bit hash values, optimized for 32 bit systems
 -}
-murmur3IntegerX86' :: String       -- ^ The string to be hashed
+murmur3IntegerX86' :: Murmur3Hashable a => a       -- ^ The hashable to be hashed
                      -> Int        -- ^ A seed value for the hash function
-                     -> IO Integer -- ^ 128 bit number generated from the string
+                     -> IO Integer -- ^ 128 bit number generated from the hashable
 murmur3IntegerX86' val seed = x128 val seed X86_128
    
 {- | Generate a 128 bit hash from the given value, this function's implementation 
@@ -97,17 +115,17 @@
      Has about 30% higher throughput than 'murmur3Int'. Be warned, though, 
      that its latency for a single 16-byte key is about 86% longer!
 -}
-murmur3IntegerX86 :: String     -- ^ The string to be hashed
+murmur3IntegerX86 :: Murmur3Hashable a => a     -- ^ The hashable to be hashed
                      -> Int     -- ^ A seed value for the hash function
-                     -> Integer -- ^ 128 bit number generated from the string
+                     -> Integer -- ^ 128 bit number generated from the hashable
 murmur3IntegerX86 val seed = US.unsafePerformIO $ murmur3IntegerX86' val seed
 
 {-$64_128
 Generate 128 bit hash values, optimized for 64 bit systems
 -}
-murmur3IntegerX64' :: String       -- ^ The string to be hashed
+murmur3IntegerX64' :: Murmur3Hashable a => a       -- ^ The hashable to be hashed
                      -> Int        -- ^ A seed value for the hash function
-                     -> IO Integer -- ^ 128 bit number generated from the string
+                     -> IO Integer -- ^ 128 bit number generated from the hashable
 murmur3IntegerX64' val seed = x128 val seed X64_128
 
 {- | Generate a 128 bit hash from the given value, this function's implementation 
@@ -115,9 +133,9 @@
      Its throughput is 250% higher than 'murmur3IntegerX86', but it has roughly 
      the same latency. 
 -}
-murmur3IntegerX64 :: String     -- ^ The string to be hashed
+murmur3IntegerX64 :: Murmur3Hashable a => a     -- ^ The hashable to be hashed
                      -> Int     -- ^ A seed value for the hash function
-                     -> Integer -- ^ 128 bit number generated from the string
+                     -> Integer -- ^ 128 bit number generated from the hashable
 murmur3IntegerX64 val seed = US.unsafePerformIO $ murmur3IntegerX64' val seed
 
 foreign import ccall "MurmurHash3_x86_32" c_x86_32
@@ -130,9 +148,9 @@
   ::  CString -> CInt -> CUInt ->  Ptr CUInt -> IO ()
 
 -- | all murmur functions use this and manipulate its response to return a different format  
-murmur3Raw :: String -> Int -> MHV -> IO [CUInt]
+murmur3Raw :: Murmur3Hashable a => a -> Int -> MHV -> IO [CUInt]
 murmur3Raw val seed ver = do
-  val' <- withCAStringLen val $ \x -> return x
+  val' <- toCstring val
   let cstr = strFromCStr val'
   let strLength = strLFromCStr val'
   outPtr <- mallocArray arrSize
@@ -149,7 +167,7 @@
         doHash X86_128 v s se o = c_x86_128 v s se o
         doHash X64_128 v s se o = c_x64_128 v s se o
 
-x128 :: String -> Int -> MHV -> IO Integer
+x128 :: Murmur3Hashable a => a -> Int -> MHV -> IO Integer
 x128 val seed ver= do 
   v <- hash ver 
   return $ twiddle 0 v 
@@ -160,4 +178,4 @@
         twiddle :: Integer -> [CUInt] -> Integer
         twiddle i [] = i
         twiddle i (0:xs) = twiddle i xs -- don't shift when val is 0
-        twiddle i (x:xs) = twiddle (B.shift i (B.bitSize x) `B.xor` fromIntegral x) xs
+        twiddle i (x:xs) = twiddle (BITS.shift i (BITS.bitSize x) `BITS.xor` fromIntegral x) xs
