diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -18,36 +18,37 @@
 import           Text.Regex.PCRE.Heavy
 ```
 
-### Matching
+### Checking
 
 ```haskell
->>> "https://unrelenting.technology" =~ [re|^http.*|] :: Bool
+>>> "https://unrelenting.technology" =~ [re|^http.*|]
 True
 ```
 
-In an `if`, you don't even need the annotation:
+### Matching (Searching)
 
-```haskell
-if "https://unrelenting.technology" =~ [re|^http.*|] then "YEP" else "NOPE"
-```
+(You can use any string type, not just String!)
 
-Extracting matches (You can use any string type, not just String)
+`scan` returns all matches as pairs like `(fullmatch, [group, group...])`.
 
 ```haskell
->>> "https://unrelenting.technology" =~ [re|^https?://([^\.]+)\..*|] :: Maybe [String]
-Just ["https://unrelenting.technology","unrelenting"]
+>>> scan [re|\s*entry (\d+) (\w+)\s*&?|] " entry 1 hello  &entry 2 hi" :: [(String, [String])]
+[
+  (" entry 1 hello  &", ["1", "hello"])
+, ("entry 2 hi",        ["2", "hi"])
+]
 ```
 
-`scan` returns all matches (search)
+It is lazy!
+If you only need the first match, use `head` (or, much better, `headMay` from [safe]) -- no extra work will be performed!
 
 ```haskell
->>> scan [re|\s*entry (\d+) (\w+)\s*&?|] " entry 1 hello  &entry 2 hi" :: [[String]]
-[
-  [" entry 1 hello  &", "1", "hello"]
-, ["entry 2 hi",        "2", "hi"]
-]
+>>> headMay $ scan [re|\s*entry (\d+) (\w+)\s*&?|] " entry 1 hello  &entry 2 hi"
+Just (" entry 1 hello  &", ["1", "hello"])
 ```
 
+[safe]: https://hackage.haskell.org/package/safe
+
 ### Replacement
 
 `sub` replaces the first match, `gsub` replaces all matches.
@@ -69,6 +70,18 @@
 -- That will get both the full match and the groups.
 -- I have no idea why you would want to use that, but that's there :-)
 ```
+
+### Options
+
+You can pass `pcre-light` options like this:
+
+```haskell
+>>> let myRe = mkRegexQQ [multiline, utf8, ungreedy]
+>>> scanO [myRe|\s*entry (\d+) (\w+)\s*&?|] [exec_no_utf8_check] " entry 1 hello  &entry 2 hi" :: [[String]]
+>>> gsubO [myRe|\d+|] [exec_notempty] "!!!NUMBER!!!" "Copyright (c) 2015 The 000 Group"
+```
+
+`utf8` is passed by default in the `re` QuasiQuoter.
 
 ## License
 
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
@@ -10,6 +10,8 @@
   (=~)
 , scan
 , scanO
+, scanRanges
+, scanRangesO
   -- * Replacement
 , sub
 , subO
@@ -18,9 +20,10 @@
   -- * QuasiQuoter
 , re
 , mkRegexQQ
-  -- * Types from pcre-light
+  -- * Types and stuff from pcre-light
 , Regex
 , PCREOption
+, PCRE.compileM
   -- * Advanced raw stuff
 , rawMatch
 , rawSub
@@ -33,43 +36,29 @@
 import           Text.Regex.PCRE.Light.Base
 import           Control.Applicative ((<$>))
 import           Data.Maybe (isJust, fromMaybe)
+import           Data.List (unfoldr)
 import           Data.Stringable
 import qualified Data.ByteString.Char8 as BS
 import qualified Data.ByteString.Internal as BS
 import           System.IO.Unsafe (unsafePerformIO)
 import           Foreign
 
-class RegexResult a where
-  fromResult :: Maybe [BS.ByteString] -> a
-
-instance RegexResult (Maybe [BS.ByteString]) where
-  fromResult = id
-
-instance Stringable a => RegexResult (Maybe [a]) where
-  fromResult x = map fromByteString <$> x
+substr :: BS.ByteString -> (Int, Int) -> BS.ByteString
+substr s (f, t) = BS.take (t - f) . BS.drop f $ s
 
-instance RegexResult Bool where
-  fromResult = isJust
+behead :: [a] -> (a, [a])
+behead (h:t) = (h, t)
+behead [] = error "no head to behead"
 
-reMatch :: (Stringable a, RegexResult b) => Regex -> a -> b
-reMatch r s = fromResult $ PCRE.match r (toByteString s) []
+reMatch :: Stringable a => Regex -> a -> Bool
+reMatch r s = isJust $ PCRE.match r (toByteString s) []
 
--- | Matches a string with a regex.
---
--- You can cast the result to Bool or Maybe [Stringable]
--- Maybe [Stringable] only represents the first match and its groups.
--- Use 'scan' to find all matches.
---
--- Note: if casts to bool automatically.
+-- | Checks whether a string matches a regex.
 --
 -- >>> :set -XQuasiQuotes
--- >>> "https://unrelenting.technology" =~ [re|^http.*|] :: Bool
+-- >>> "https://unrelenting.technology" =~ [re|^http.*|]
 -- True
--- >>> "https://unrelenting.technology" =~ [re|^https?://([^\.]+)\..*|] :: Maybe [String]
--- Just ["https://unrelenting.technology","unrelenting"]
--- >>> if "https://unrelenting.technology" =~ [re|^http.*|] then "YEP" else "NOPE"
--- "YEP"
-(=~) :: (Stringable a, RegexResult b) => a -> Regex -> b
+(=~) :: Stringable a => a -> Regex -> Bool
 (=~) = flip reMatch
 
 -- | Does raw PCRE matching (you probably shouldn't use this directly).
@@ -102,26 +91,46 @@
                   loop (n + 1) (o + 2) ((fromIntegral i, fromIntegral j) : acc)
           in loop 0 0 []
 
-substr :: BS.ByteString -> (Int, Int) -> BS.ByteString
-substr s (f, t) = BS.take (t - f) . BS.drop f $ s
+nextMatch :: Regex -> [PCREExecOption] -> BS.ByteString -> Int -> Maybe ([(Int, Int)], Int)
+nextMatch r opts str offset =
+  case rawMatch r str offset opts of
+    Nothing -> Nothing
+    Just [] -> Nothing
+    Just ms -> Just (ms, maximum $ map snd ms)
 
 -- | Searches the string for all matches of a given regex.
 --
 -- >>> scan [re|\s*entry (\d+) (\w+)\s*&?|] " entry 1 hello  &entry 2 hi"
--- [[" entry 1 hello  &","1","hello"],["entry 2 hi","2","hi"]]
-scan :: (Stringable a) => Regex -> a -> [[a]]
+-- [(" 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"
+-- (" entry 1 hello  &",["1","hello"])
+scan :: (Stringable a) => 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]]
-scanO r opts s = map fromByteString <$> loop 0 []
+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
-        loop offset acc =
-          case rawMatch r str offset opts of
-            Nothing -> reverse acc
-            Just [] -> reverse acc
-            Just ms -> loop (maximum $ map snd ms) ((map (substr str) ms) : acc)
 
+-- | 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"
+-- [((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 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 r opts s = map behead $ unfoldr (nextMatch r opts str) 0
+  where str = toByteString s
+
 class RegexReplacement a where
   performReplacement :: BS.ByteString -> [BS.ByteString] -> a -> BS.ByteString
 
@@ -187,11 +196,12 @@
             _ -> acc
 
 instance Lift PCREOption where
-  lift o = [| o |]
+  -- 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 (BS.pack txt) opts |]
-  where !_ = PCRE.compile (BS.pack txt) opts -- check at compile time
+quoteExpRegex opts txt = [| PCRE.compile (toByteString (txt :: String)) opts |]
+  where !_ = PCRE.compile (toByteString txt) opts -- check at compile time
 
 -- | Returns a QuasiQuoter like 're', but with given PCRE options.
 mkRegexQQ :: [PCREOption] -> QuasiQuoter
@@ -203,4 +213,4 @@
 
 -- | A QuasiQuoter for regular expressions that does a compile time check.
 re :: QuasiQuoter
-re = mkRegexQQ []
+re = mkRegexQQ [utf8]
diff --git a/pcre-heavy.cabal b/pcre-heavy.cabal
--- a/pcre-heavy.cabal
+++ b/pcre-heavy.cabal
@@ -1,7 +1,13 @@
 name:            pcre-heavy
-version:         0.1.0
+version:         0.2.0
 synopsis:        A regexp library on top of pcre-light you can actually use.
-description:     https://github.com/myfreeweb/pcre-heavy
+description:
+    A regular expressions library that does not suck.
+
+    - based on <https://hackage.haskell.org/package/pcre-light pcre-light>
+    - takes and returns <https://hackage.haskell.org/package/stringable Stringables> everywhere
+    - a QuasiQuoter for regexps that does compile time checking
+    - SEARCHES FOR MULTIPLE MATCHES! DOES REPLACEMENT!
 category:        Web
 homepage:        https://github.com/myfreeweb/pcre-heavy
 author:          Greg V
