diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -2,19 +2,20 @@
 
 *Finally!* A Haskell regular expressions library that does not suck.
 
-- based on [pcre-light], none of that regex-compat-pluggable-backend stuff
-- takes and returns [Stringables] everywhere, use ANY STRING TYPE (String, ByteString, LByteString, Text, LText, FilePath) -- but you need a bit more type annotations than usual
+- based on [pcre-light], none of that regex-base complicated pluggable-backend stuff
+- takes and returns [ConvertibleStrings] everywhere, use ANY STRING TYPE (String, ByteString, Lazy ByteString, Text, Lazy Text) -- but you need a bit more type annotations (or [ClassyPrelude]'s `asText`, `asString`, etc.) if you use `OverloadedStrings` which you probably can't live without
 - a QuasiQuoter for regexps that does compile time checking (BTW, [vim2hs] has correct syntax highlighting for that!)
 - **SEARCHES FOR MULTIPLE MATCHES! DOES REPLACEMENT!**
 
 [pcre-light]: https://hackage.haskell.org/package/pcre-light
-[Stringables]: https://hackage.haskell.org/package/stringable
+[ConvertibleStrings]: https://hackage.haskell.org/package/string-conversions
+[ClassyPrelude]: https://hackage.haskell.org/package/classy-prelude
 [vim2hs]: https://github.com/dag/vim2hs#quasi-quoting
 
 ## Usage
 
 ```haskell
-{-# LANGUAGE QuasiQuotes #-}
+{-# LANGUAGE QuasiQuotes, FlexibleContexts #-}
 import           Text.Regex.PCRE.Heavy
 ```
 
diff --git a/library/Text/Regex/PCRE/Heavy.hs b/library/Text/Regex/PCRE/Heavy.hs
--- a/library/Text/Regex/PCRE/Heavy.hs
+++ b/library/Text/Regex/PCRE/Heavy.hs
@@ -1,9 +1,7 @@
 {-# OPTIONS_GHC -fno-warn-orphans -fno-warn-unused-binds #-}
-{-# LANGUAGE UndecidableInstances #-}
-{-# LANGUAGE FlexibleInstances, BangPatterns #-}
-{-# LANGUAGE TemplateHaskell, QuasiQuotes #-}
+{-# LANGUAGE UndecidableInstances, FlexibleInstances, FlexibleContexts, BangPatterns #-}
+{-# LANGUAGE TemplateHaskell, QuasiQuotes, UnicodeSyntax, CPP #-}
 {-# LANGUAGE ForeignFunctionInterface #-}
-{-# LANGUAGE UnicodeSyntax, CPP #-}
 
 -- | A usable regular expressions library on top of pcre-light.
 module Text.Regex.PCRE.Heavy (
@@ -34,7 +32,7 @@
 , rawSub
 ) where
 
-#if __GLASGOW_HASKELL__ < 709
+#if !MIN_VERSION_base(4,8,0)
 import           Control.Applicative ((<$>))
 #endif
 import           Language.Haskell.TH hiding (match)
@@ -44,33 +42,32 @@
 import           Text.Regex.PCRE.Light.Base
 import           Data.Maybe (isJust, fromMaybe)
 import           Data.List (unfoldr, mapAccumL)
-import           Data.Stringable
+import           Data.String.Conversions
 import qualified Data.ByteString.Char8 as BS
 import qualified Data.ByteString.Internal as BS
 import           System.IO.Unsafe (unsafePerformIO)
 import           Foreign (withForeignPtr, allocaBytes, nullPtr, plusPtr, peekElemOff)
-import           Debug.Trace
 
-substr ∷ BS.ByteString → (Int, Int) → BS.ByteString
+substr ∷ SBS → (Int, Int) → SBS
 substr s (f, t) = BS.take (t - f) . BS.drop f $ s
 
 behead ∷ [a] → (a, [a])
 behead (h:t) = (h, t)
 behead [] = error "no head to behead"
 
-reMatch ∷ Stringable a ⇒ Regex → a → Bool
-reMatch r s = isJust $ PCRE.match r (toByteString s) []
+reMatch ∷ (ConvertibleStrings SBS a, ConvertibleStrings a SBS) ⇒ Regex → a → Bool
+reMatch r s = isJust $ PCRE.match r (cs s) []
 
 -- | Checks whether a string matches a regex.
 --
 -- >>> :set -XQuasiQuotes
+-- >>> :set -XFlexibleContexts
 -- >>> "https://unrelenting.technology" =~ [re|^http.*|]
 -- True
-(=~) ∷ Stringable a ⇒ a → Regex → Bool
+(=~), (≈) ∷ (ConvertibleStrings SBS a, ConvertibleStrings a SBS) ⇒ a → Regex → Bool
 (=~) = flip reMatch
 
 -- | Same as =~.
-(≈) ∷ Stringable a ⇒ a → Regex → Bool
 (≈) = (=~)
 
 -- | Does raw PCRE matching (you probably shouldn't use this directly).
@@ -82,7 +79,7 @@
 -- Just [(7,9)]
 -- >>> rawMatch [re|(\w)(\w)|] "a a ab abc ba" 0 []
 -- Just [(4,6),(4,5),(5,6)]
-rawMatch ∷ Regex → BS.ByteString → Int → [PCREExecOption] → Maybe [(Int, Int)]
+rawMatch ∷ Regex → SBS → Int → [PCREExecOption] → Maybe [(Int, Int)]
 rawMatch r@(Regex pcreFp _) s offset opts = unsafePerformIO $ do
   withForeignPtr pcreFp $ \pcrePtr → do
     let nCapt = PCRE.captureCount r
@@ -103,7 +100,7 @@
                   loop (n + 1) (o + 2) ((fromIntegral i, fromIntegral j) : acc)
           in loop 0 0 []
 
-nextMatch ∷ Regex → [PCREExecOption] → BS.ByteString → Int → Maybe ([(Int, Int)], Int)
+nextMatch ∷ Regex → [PCREExecOption] → SBS → Int → Maybe ([(Int, Int)], Int)
 nextMatch r opts str offset =
   case rawMatch r str offset opts of
     Nothing → Nothing
@@ -112,53 +109,53 @@
 
 -- | Searches the string for all matches of a given regex.
 --
--- >>> scan [re|\s*entry (\d+) (\w+)\s*&?|] " entry 1 hello  &entry 2 hi"
+-- >>> scan [re|\s*entry (\d+) (\w+)\s*&?|] (" entry 1 hello  &entry 2 hi" :: String)
 -- [(" entry 1 hello  &",["1","hello"]),("entry 2 hi",["2","hi"])]
 --
 -- It is lazy! If you only need the first match, just apply 'head' (or
 -- 'headMay' from the "safe" library) -- no extra work will be performed!
 --
--- >>> head $ scan [re|\s*entry (\d+) (\w+)\s*&?|] " entry 1 hello  &entry 2 hi"
+-- >>> head $ scan [re|\s*entry (\d+) (\w+)\s*&?|] (" entry 1 hello  &entry 2 hi" :: String)
 -- (" entry 1 hello  &",["1","hello"])
-scan ∷ (Stringable a) ⇒ Regex → a → [(a, [a])]
+scan ∷ (ConvertibleStrings SBS a, ConvertibleStrings a SBS) ⇒ Regex → a → [(a, [a])]
 scan r s = scanO r [] s
 
 -- | Exactly like 'scan', but passes runtime options to PCRE.
-scanO ∷ (Stringable a) ⇒ Regex → [PCREExecOption] → a → [(a, [a])]
-scanO r opts s = map behead $ map (fromByteString . substr str) <$> unfoldr (nextMatch r opts str) 0
-  where str = toByteString s
+scanO ∷ (ConvertibleStrings SBS a, ConvertibleStrings a SBS) ⇒ Regex → [PCREExecOption] → a → [(a, [a])]
+scanO r opts s = map behead $ map (cs . substr str) <$> unfoldr (nextMatch r opts str) 0
+  where str = cs s
 
 -- | Searches the string for all matches of a given regex, like 'scan', but
 -- returns positions inside of the string.
 --
--- >>> scanRanges [re|\s*entry (\d+) (\w+)\s*&?|] " entry 1 hello  &entry 2 hi"
+-- >>> scanRanges [re|\s*entry (\d+) (\w+)\s*&?|] (" entry 1 hello  &entry 2 hi" :: String)
 -- [((0,17),[(7,8),(9,14)]),((17,27),[(23,24),(25,27)])]
 --
 -- And just like 'scan', it's lazy.
-scanRanges ∷ (Stringable a) ⇒ Regex → a → [((Int, Int), [(Int, Int)])]
+scanRanges ∷ (ConvertibleStrings SBS a, ConvertibleStrings a SBS) ⇒ Regex → a → [((Int, Int), [(Int, Int)])]
 scanRanges r s = scanRangesO r [] s
 
 -- | Exactly like 'scanRanges', but passes runtime options to PCRE.
-scanRangesO ∷ Stringable a ⇒ Regex → [PCREExecOption] → a → [((Int, Int), [(Int, Int)])]
+scanRangesO ∷ (ConvertibleStrings SBS a, ConvertibleStrings a SBS) ⇒ Regex → [PCREExecOption] → a → [((Int, Int), [(Int, Int)])]
 scanRangesO r opts s = map behead $ unfoldr (nextMatch r opts str) 0
-  where str = toByteString s
+  where str = cs s
 
 class RegexReplacement a where
-  performReplacement ∷ BS.ByteString → [BS.ByteString] → a → BS.ByteString
+  performReplacement ∷ SBS → [SBS] → a → SBS
 
-instance {-# OVERLAPPABLE #-} Stringable a ⇒ RegexReplacement a where
-  performReplacement _ _ to = toByteString to
+instance {-# OVERLAPPABLE #-} ConvertibleStrings a SBS ⇒ RegexReplacement a where
+  performReplacement _ _ to = cs to
 
-instance Stringable a ⇒ RegexReplacement (a → [a] → a) where
-  performReplacement from groups replacer = toByteString $ replacer (fromByteString from) (map fromByteString groups)
+instance (ConvertibleStrings SBS a, ConvertibleStrings a SBS) ⇒ RegexReplacement (a → [a] → a) where
+  performReplacement from groups replacer = cs $ replacer (cs from) (map cs groups)
 
-instance Stringable a ⇒ RegexReplacement (a → a) where
-  performReplacement from _ replacer = toByteString $ replacer (fromByteString from)
+instance (ConvertibleStrings SBS a, ConvertibleStrings a SBS) ⇒ RegexReplacement (a → a) where
+  performReplacement from _ replacer = cs $ replacer (cs from)
 
-instance Stringable a ⇒ RegexReplacement ([a] → a) where
-  performReplacement _ groups replacer = toByteString $ replacer (map fromByteString groups)
+instance (ConvertibleStrings SBS a, ConvertibleStrings a SBS) ⇒ RegexReplacement ([a] → a) where
+  performReplacement _ groups replacer = cs $ replacer (map cs groups)
 
-rawSub ∷ RegexReplacement r ⇒ Regex → r → BS.ByteString → Int → [PCREExecOption] → Maybe (BS.ByteString, Int)
+rawSub ∷ RegexReplacement r ⇒ Regex → r → SBS → Int → [PCREExecOption] → Maybe (SBS, Int)
 rawSub r t s offset opts =
   case rawMatch r s offset opts of
     Just ((begin, end):groups) →
@@ -176,22 +173,22 @@
 -- >>> sub [re|a|] "b" "c" :: String
 -- "c"
 --
--- >>> sub [re|bad|] "xxxbad" "this is bad, right?"
+-- >>> sub [re|bad|] "xxxbad" "this is bad, right?" :: String
 -- "this is xxxbad, right?"
 --
 -- You can use functions!
--- A function of Stringable gets the full match.
--- A function of [Stringable] gets the groups.
--- A function of Stringable → [Stringable] gets both.
+-- A function of ConvertibleStrings SBS gets the full match.
+-- A function of [ConvertibleStrings SBS] gets the groups.
+-- A function of ConvertibleStrings SBS → [ConvertibleStrings SBS] gets both.
 --
 -- >>> sub [re|%(\d+)(\w+)|] (\(d:w:_) -> "{" ++ d ++ " of " ++ w ++ "}" :: String) "Hello, %20thing" :: String
 -- "Hello, {20 of thing}"
-sub ∷ (Stringable a, RegexReplacement r) ⇒ Regex → r → a → a
+sub ∷ (ConvertibleStrings SBS a, ConvertibleStrings a SBS, RegexReplacement r) ⇒ Regex → r → a → a
 sub r t s = subO r [] t s
 
 -- | Exactly like 'sub', but passes runtime options to PCRE.
-subO ∷ (Stringable a, RegexReplacement r) ⇒ Regex → [PCREExecOption] → r → a → a
-subO r opts t s = fromMaybe s $ fromByteString <$> fst <$> rawSub r t (toByteString s) 0 opts
+subO ∷ (ConvertibleStrings SBS a, ConvertibleStrings a SBS, RegexReplacement r) ⇒ Regex → [PCREExecOption] → r → a → a
+subO r opts t s = fromMaybe s $ cs <$> fst <$> rawSub r t (cs s) 0 opts
 
 -- | Replaces all occurences of a given regex.
 --
@@ -204,18 +201,18 @@
 -- "Hello, world"
 --
 -- https://github.com/myfreeweb/pcre-heavy/issues/2
--- >>> gsub [re|good|] "bad" "goodgoodgood"
+-- >>> gsub [re|good|] "bad" "goodgoodgood" :: String
 -- "badbadbad"
 --
--- >>> gsub [re|bad|] "xxxbad" "this is bad, right? bad"
+-- >>> gsub [re|bad|] "xxxbad" "this is bad, right? bad" :: String
 -- "this is xxxbad, right? xxxbad"
-gsub ∷ (Stringable a, RegexReplacement r) ⇒ Regex → r → a → a
+gsub ∷ (ConvertibleStrings SBS a, ConvertibleStrings a SBS, RegexReplacement r) ⇒ Regex → r → a → a
 gsub r t s = gsubO r [] t s
 
 -- | Exactly like 'gsub', but passes runtime options to PCRE.
-gsubO ∷ (Stringable a, RegexReplacement r) ⇒ Regex → [PCREExecOption] → r → a → a
-gsubO r opts t s = fromByteString $ loop 0 str
-  where str = toByteString s
+gsubO ∷ (ConvertibleStrings SBS a, ConvertibleStrings a SBS, RegexReplacement r) ⇒ Regex → [PCREExecOption] → r → a → a
+gsubO r opts t s = cs $ loop 0 str
+  where str = cs s
         loop offset acc =
           case rawSub r t acc offset opts of
             Just (result, newOffset) →
@@ -226,30 +223,30 @@
 --
 -- Is lazy.
 --
--- >>> split [re|%(begin|next|end)%|] "%begin%hello%next%world%end%"
+-- >>> split [re|%(begin|next|end)%|] ("%begin%hello%next%world%end%" :: String)
 -- ["","hello","world",""]
 --
--- >>> split [re|%(begin|next|end)%|] ""
+-- >>> split [re|%(begin|next|end)%|] ("" :: String)
 -- [""]
-split ∷ Stringable a ⇒ Regex → a → [a]
+split ∷ (ConvertibleStrings SBS a, ConvertibleStrings a SBS) ⇒ Regex → a → [a]
 split r s = splitO r [] s
 
 -- | Exactly like 'split', but passes runtime options to PCRE.
-splitO ∷ Stringable a ⇒ Regex → [PCREExecOption] → a → [a]
-splitO r opts s = map fromByteString $ map' (substr str) partRanges
+splitO ∷ (ConvertibleStrings SBS a, ConvertibleStrings a SBS) ⇒ Regex → [PCREExecOption] → a → [a]
+splitO r opts s = map cs $ map' (substr str) partRanges
   where map' f = foldr ((:) . f) [f (lastL, BS.length str)] -- avoiding the snoc operation
         (lastL, partRanges) = mapAccumL invRange 0 ranges
         invRange acc (xl, xr) = (xr, (acc, xl))
         ranges = map fst $ scanRangesO r opts str
-        str = toByteString s
+        str = cs s
 
 instance Lift PCREOption where
   -- well, the constructor isn't exported, but at least it implements Read/Show :D
   lift o = let o' = show o in [| read o' ∷ PCREOption |]
 
 quoteExpRegex ∷ [PCREOption] → String → ExpQ
-quoteExpRegex opts txt = [| PCRE.compile (toByteString (txt ∷ String)) opts |]
-  where !_ = PCRE.compile (toByteString txt) opts -- check at compile time
+quoteExpRegex opts txt = [| PCRE.compile (cs (txt ∷ String)) opts |]
+  where !_ = PCRE.compile (cs txt) opts -- check at compile time
 
 -- | Returns a QuasiQuoter like 're', but with given PCRE options.
 mkRegexQQ ∷ [PCREOption] → QuasiQuoter
diff --git a/pcre-heavy.cabal b/pcre-heavy.cabal
--- a/pcre-heavy.cabal
+++ b/pcre-heavy.cabal
@@ -1,5 +1,5 @@
 name:            pcre-heavy
-version:         0.2.5
+version:         1.0.0
 synopsis:        A regexp library on top of pcre-light you can actually use.
 description:
     A regular expressions library that does not suck.
@@ -34,12 +34,11 @@
         base >= 4.3.0.0 && < 5
       , pcre-light
       , bytestring
-      , stringable
+      , string-conversions
       , template-haskell
     default-language: Haskell2010
     exposed-modules:
         Text.Regex.PCRE.Heavy
-    ghc-prof-options: -prof
     ghc-options: -Wall
     hs-source-dirs: library
 
