diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -26,16 +26,18 @@
 
 These can also be given custom inflection matchers
 
-```
+```haskell
 λ: :t singularizeWith
 [Inflection] -> Text -> Text
 ```
 
 There are 3 different types of transformations:
 
-Match (takes a PCRE regex and a replacement string)
+### Match
 
-```
+Takes a PCRE regex and a replacement string.
+
+```haskell
 λ: :t makeMatchMapping
 [(RegexPattern, RegexReplace)] -> [Inflection]
 
@@ -44,9 +46,11 @@
 "octopi"
 ```
 
-Irregular (from singular to plural with no greater pattern)
+### Irregular
 
-```
+From singular to plural with no greater pattern.
+
+```haskell
 λ: :t makeIrregularMapping
 [(Singular, Plural)] -> [Inflection]
 
@@ -55,8 +59,11 @@
 "zombies"
 ```
 
-Uncountable (doesn't have a mapping, word stays the same) so it has the type:
-```
+### Uncountable
+
+Doesn't have a mapping, word stays the same) so it has the type:
+
+```haskell
 [Text] -> [Inflection]
 ```
 
diff --git a/Text/Countable.hs b/Text/Countable.hs
--- a/Text/Countable.hs
+++ b/Text/Countable.hs
@@ -22,12 +22,13 @@
   )
 where
 
-import Data.Maybe (catMaybes, fromMaybe)
-import Data.Monoid ((<>))
+import Data.Maybe (catMaybes, fromMaybe, isNothing)
 import Data.Text as T
 import Data.Text.Encoding (decodeUtf8, encodeUtf8)
 import Text.Countable.Data
-import Text.Regex.PCRE.Light
+import Text.Regex.PCRE.ByteString
+import Text.Regex.PCRE.ByteString.Utils (substitute')
+import System.IO.Unsafe
 
 type RegexPattern = T.Text
 type RegexReplace = T.Text
@@ -38,6 +39,8 @@
   = Simple (Singular, Plural)
   | Match (Maybe Regex, RegexReplace)
 
+data MatchType = HasMatch | HasNoMatch
+
 -- | pluralize a word given a default mapping
 pluralize :: T.Text -> T.Text
 pluralize = pluralizeWith mapping
@@ -108,34 +111,23 @@
 runSub (Just reg, rep) t = matchWithReplace (reg, rep) t
 
 matchWithReplace :: (Regex, RegexReplace) -> T.Text -> Maybe T.Text
-matchWithReplace (reg, rep) t = do
-  matched : grouping <- regexMatch t reg
-  return $ (t `without` matched) <> groupReplace grouping rep
+matchWithReplace (reg, rep) t = case regexMatch t reg of
+  HasNoMatch -> Nothing
+  HasMatch   -> toMaybe $ substitute' reg (encodeUtf8 t) (encodeUtf8 rep)
   where
-    without t1 t2 = if t2 == "" then t1 else T.replace t2 "" t1
-
-groupReplace :: [T.Text] -> T.Text -> T.Text
-groupReplace g rep =
-  case g of
-    [] -> rep
-    (g':_) -> g' <> additions
-    where
-      rep' = tailMaybe $ T.split ((==) '\1') rep
-      additions = T.concat $ fromMaybe [] rep'
+    toMaybe = either (const Nothing) (Just . decodeUtf8)
 
-regexMatch :: T.Text -> Regex -> Maybe [T.Text]
-regexMatch t r = do
-  bs <- match r (encodeUtf8 t) []
-  return $ fmap decodeUtf8 bs
+regexMatch :: T.Text -> Regex -> MatchType
+regexMatch t r = case match of
+                   Left _ -> HasNoMatch
+                   Right m -> if isNothing m then HasNoMatch else HasMatch
+  where match = unsafePerformIO $ execute r (encodeUtf8 t)
 
 regexPattern :: T.Text -> Maybe Regex
-regexPattern pat = toMaybe $ compileM (encodeUtf8 pat) [caseless]
+regexPattern pat = toMaybe reg
   where toMaybe = either (const Nothing) Just
+        reg = unsafePerformIO $ compile compCaseless execBlank (encodeUtf8 pat)
 
 headMaybe :: [a] -> Maybe a
 headMaybe [] = Nothing
 headMaybe (x:_) = Just x
-
-tailMaybe :: [a] -> Maybe [a]
-tailMaybe [] = Nothing
-tailMaybe (_:xs) = Just xs
diff --git a/Text/Countable/Data.hs b/Text/Countable/Data.hs
--- a/Text/Countable/Data.hs
+++ b/Text/Countable/Data.hs
@@ -20,25 +20,25 @@
 defaultPlurals' =
   [ ("$", "s")
   , ("s$", "s")
-  , ("^(ax|test)is$", "\1es")
-  , ("(octop|vir)us$", "\1i")
-  , ("(octop|vir)i$", "\1i")
-  , ("(alias|status)$", "\1es")
-  , ("(bu)s$", "\1ses")
-  , ("(buffal|tomat)o$", "\1oes")
-  , ("([ti])um$", "\1a")
-  , ("([ti])a$", "\1a")
+  , ("^(ax|test)is$", "\\1es")
+  , ("(octop|vir)us$", "\\1i")
+  , ("(octop|vir)i$", "\\1i")
+  , ("(alias|status)$", "\\1es")
+  , ("(bu)s$", "\\1ses")
+  , ("(buffal|tomat)o$", "\\1oes")
+  , ("([ti])um$", "\\1a")
+  , ("([ti])a$", "\\1a")
   , ("sis$", "ses")
-  , ("(?:([^f])fe|([lr])f)$", "\1\2ves")
-  , ("(hive)$", "\1s")
-  , ("([^aeiouy]|qu)y$", "\1ies")
-  , ("(x|ch|ss|sh)$", "\1es")
-  , ("(matr|vert|ind)(?:ix|ex)$", "\1ices")
-  , ("^(m|l)ouse$", "\1ice")
-  , ("^(m|l)ice$", "\1ice")
-  , ("^(ox)$", "\1en")
-  , ("^(oxen)$", "\1")
-  , ("(quiz)$", "\1zes")
+  , ("(?:([^f])fe|([lr])f)$", "\\1\2ves")
+  , ("(hive)$", "\\1s")
+  , ("([^aeiouy]|qu)y$", "\\1ies")
+  , ("(x|ch|ss|sh)$", "\\1es")
+  , ("(matr|vert|ind)(?:ix|ex)$", "\\1ices")
+  , ("^(m|l)ouse$", "\\1ice")
+  , ("^(m|l)ice$", "\\1ice")
+  , ("^(ox)$", "\\1en")
+  , ("^(oxen)$", "\\1")
+  , ("(quiz)$", "\\1zes")
   ]
 
 -- |These default inflections stolen from the Ruby inflection library - see
@@ -46,32 +46,32 @@
 defaultSingulars' :: [(Text, Text)]
 defaultSingulars' =
   [ ("s$", "")
-  , ("(ss)$", "\1")
-  , ("(n)ews$", "\1ews")
-  , ("([ti])a$", "\1um")
-  , ("((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)(sis|ses)$", "\1sis")
-  , ("(^analy)(sis|ses)$", "\1sis")
-  , ("([^f])ves$", "\1fe")
-  , ("(hive)s$", "\1")
-  , ("(tive)s$", "\1")
-  , ("([lr])ves$", "\1f")
-  , ("([^aeiouy]|qu)ies$", "\1y")
-  , ("(s)eries$", "\1eries")
-  , ("(m)ovies$", "\1ovie")
-  , ("(x|ch|ss|sh)es$", "\1")
-  , ("^(m|l)ice$", "\1ouse")
-  , ("(bus)(es)?$", "\1")
-  , ("(o)es$", "\1")
-  , ("(shoe)s$", "\1")
-  , ("(cris|test)(is|es)$", "\1is")
-  , ("^(a)x[ie]s$", "\1xis")
-  , ("(octop|vir)(us|i)$", "\1us")
-  , ("(alias|status)(es)?$", "\1")
-  , ("^(ox)en", "\1")
-  , ("(vert|ind)ices$", "\1ex")
-  , ("(matr)ices$", "\1ix")
-  , ("(quiz)zes$", "\1")
-  , ("(database)s$", "\1")
+  , ("(ss)$", "\\1")
+  , ("(n)ews$", "\\1ews")
+  , ("([ti])a$", "\\1um")
+  , ("((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)(sis|ses)$", "\\1sis")
+  , ("(^analy)(sis|ses)$", "\\1sis")
+  , ("([^f])ves$", "\\1fe")
+  , ("(hive)s$", "\\1")
+  , ("(tive)s$", "\\1")
+  , ("([lr])ves$", "\\1f")
+  , ("([^aeiouy]|qu)ies$", "\\1y")
+  , ("(s)eries$", "\\1eries")
+  , ("(m)ovies$", "\\1ovie")
+  , ("(x|ch|ss|sh)es$", "\\1")
+  , ("^(m|l)ice$", "\\1ouse")
+  , ("(bus)(es)?$", "\\1")
+  , ("(o)es$", "\\1")
+  , ("(shoe)s$", "\\1")
+  , ("(cris|test)(is|es)$", "\\1is")
+  , ("^(a)x[ie]s$", "\\1xis")
+  , ("(octop|vir)(us|i)$", "\\1us")
+  , ("(alias|status)(es)?$", "\\1")
+  , ("^(ox)en", "\\1")
+  , ("(vert|ind)ices$", "\\1ex")
+  , ("(matr)ices$", "\\1ix")
+  , ("(quiz)zes$", "\\1")
+  , ("(database)s$", "\\1")
   ]
 
 -- |These default irregular inflections stolen from the Ruby inflection library - see
diff --git a/countable-inflections.cabal b/countable-inflections.cabal
--- a/countable-inflections.cabal
+++ b/countable-inflections.cabal
@@ -1,5 +1,5 @@
 name:                countable-inflections
-version:             0.1.0
+version:             0.2.0
 synopsis:            Countable Text Inflections
 description:
   Provides methods for singularizing and pluralizing text.
@@ -35,7 +35,8 @@
       base         >= 4.6   && < 4.10
     , exceptions   >= 0.6   && < 0.9
     , text         >= 0.2   && < 1.3
-    , pcre-light
+    , regex-pcre-builtin
+    , pcre-utils
     , bytestring
   default-language:    Haskell2010
 
diff --git a/test/Text/CountableSpec.hs b/test/Text/CountableSpec.hs
--- a/test/Text/CountableSpec.hs
+++ b/test/Text/CountableSpec.hs
@@ -36,6 +36,9 @@
       singularize "mice" `shouldBe` "mouse"
       singularize "oxen" `shouldBe` "ox"
       singularize "branches" `shouldBe` "branch"
+      singularize "transactions" `shouldBe` "transaction"
+      singularize "sessions" `shouldBe` "session"
+      singularize "users" `shouldBe` "user"
 
 
 irregularCases :: Spec
