diff --git a/ChangeLog.md b/ChangeLog.md
new file mode 100644
--- /dev/null
+++ b/ChangeLog.md
@@ -0,0 +1,13 @@
+See also http://pvp.haskell.org/faq
+
+## 0.94.0.0
+
+- **Breaking change**: Switch RegExp API from the previously used `Monad(fail)` to `MonadFail(fail)` to denote matching failures
+
+- Define `Extract Text` instances for strict and lazy `Text` types
+
+- Compatibility with `base-4.13.0`
+
+- Explicitly declare all modules `Safe` under SafeHaskell for GHC 7.4 and higher
+
+----
diff --git a/Text/Regex/Base.hs b/Text/Regex/Base.hs
deleted file mode 100644
--- a/Text/Regex/Base.hs
+++ /dev/null
@@ -1,56 +0,0 @@
-{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies #-}
------------------------------------------------------------------------------
--- |
---
--- Module      :  Text.Regex.Base
--- Copyright   :  (c) Chris Kuklewicz 2006
--- License     :  BSD-style (see the file LICENSE)
--- 
--- Maintainer  :  libraries@haskell.org, textregexlazy@personal.mightyreason.com
--- Stability   :  experimental
--- Portability :  non-portable (MPTC+FD)
---
--- Classes and instances for Regex matching.
---
--- 
--- This module merely imports and re-exports the common part of the new
--- api: "Text.Regex.Base.RegexLike" and "Text.Regex.Base.Context".
--- 
--- To see what result types the instances of RegexContext can produce,
--- please read the "Text.Regex.Base.Context" haddock documentation.
--- 
--- This does not provide any of the backends, just the common interface
--- they all use.  The modules which provide the backends and their cabal
--- packages are:
--- 
---  * @Text.Regex.Posix@ from regex-posix
--- 
---  * @Text.Regex@ from regex-compat (uses regex-posix)
--- 
---  * @Text.Regex.Parsec@ from regex-parsec
--- 
---  * @Text.Regex.DFA@ from regex-dfa
--- 
---  * @Text.Regex.PCRE@ from regex-pcre
--- 
---  * @Test.Regex.TRE@ from regex-tre
--- 
--- In fact, just importing one of the backends is adequate, you do not
--- also need to import this module.
--- 
--- TODO: Copy Example*hs files into this haddock comment
------------------------------------------------------------------------------
-
-module Text.Regex.Base (getVersion_Text_Regex_Base
-  -- | RegexLike defines classes and type, and 'Extract' instances
-  ,module Text.Regex.Base.RegexLike) where
-
-import Data.Version(Version(..))
-import Text.Regex.Base.RegexLike
-import Text.Regex.Base.Context()
-
-getVersion_Text_Regex_Base :: Version
-getVersion_Text_Regex_Base =
-  Version { versionBranch = [0,93,2]
-          , versionTags = ["unstable"]
-          }
diff --git a/Text/Regex/Base/Context.hs b/Text/Regex/Base/Context.hs
deleted file mode 100644
--- a/Text/Regex/Base/Context.hs
+++ /dev/null
@@ -1,409 +0,0 @@
-{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies #-}
-{-# OPTIONS_GHC -fno-warn-orphans #-}
-{-|
-
-Module      :  Text.Regex.Base.Context
-Copyright   :  (c) Chris Kuklewicz 2006
-License     :  BSD-style (see the file LICENSE)
-
-Maintainer  :  libraries@haskell.org, textregexlazy@personal.mightyreason.com
-Stability   :  experimental
-Portability :  non-portable (MPTC+FD)
-
-This is a module of instances of 'RegexContext' (defined in
-Text.Regex.Base.RegexLike).  Nothing else is exported.  This is
-usually imported via the Text.Regex.Base convenience package which
-itself is re-exported from newer Text.Regex.XXX modules provided by
-the different regex-xxx backends.
-
-These instances work for all the supported types and backends
-interchangably.  These instances provide the different results that
-can be gotten from a match or matchM operation (often via the @=~@ and
-@=~~@ operators with combine @makeRegex@ with @match@ and @matchM@
-respectively).  This module name is Context because they operators are
-context dependent: use them in a context that expects an Int and you
-get a count of matches, use them in a Bool context and get True if
-there is a match, etc.
-
-@RegexContext a b c@ takes a regular expression suppied in a type 'a'
-generated by 'RegexMaker' and a target text supplied in type 'b' to a
-result type 'c' using the 'match' class function.  The 'matchM' class
-function works like 'match' unless there is no match found, in which
-case it calls 'fail' in the (arbitrary) monad context.
-
-There are a few type synonyms from RegexLike that are used here:
-
-@ 
--- | 0 based index from start of source, or (-1) for unused
-type MatchOffset = Int
--- | non-negative length of a match
-type MatchLength = Int
-type MatchArray = Array Int (MatchOffset, MatchLength)
-type MatchText source = Array Int (source, (MatchOffset, MatchLength))
-@
-
-There are also a few newtypes that used to prevent any possible
-overlap of types, which were not needed for GHC's late overlap
-detection but are needed for use in Hugs.
-
-@
-newtype AllSubmatches f b = AllSubmatches {getAllSubmatches :: (f b)}
-newtype AllTextSubmatches f b = AllTextSubmatches {getAllTextSubmatches :: (f b)}
-newtype AllMatches f b = AllMatches {getAllMatches :: (f b)}
-newtype AllTextMatches f b = AllTextMatches {getAllTextMatches :: (f b) }
-@
-
-The newtypes' @f@ parameters are the containers, usually @[]@ or
-@Array Int@, (where the arrays all have lower bound 0).
-
-The two *Submatches newtypes return only information on the first
-match.  The other two newtypes return information on all the
-non-overlapping matches.  The two *Text* newtypes are used to mark
-result types that contain the same type as the target text.
-
-Where provided, noncaptured submatches will have a @MatchOffset@ of
-(-1) and non-negative otherwise.  The semantics of submatches depend
-on the backend and its compile and execution options.  Where provided,
-@MatchLength@ will always be non-negative.  Arrays with no elements
-are returned with bounds of (1,0).  Arrays with elements will have a
-lower bound of 0.
-
-XXX THIS HADDOCK DOCUMENTATION IS OUT OF DATE XXX
-
-These are for finding the first match in the target text:
-
-
-@ RegexContext a b Bool @ :
-  Whether there is any match or not.
-
-
-@ RegexContext a b () @ :
-  Useful as a guard with @matchM@ or @=~~@ in a monad, since failure to match calls 'fail'.
-
-
-@ RegexContext a b b @ :
-  This returns the text of the whole match.
-  It will return 'empty' from the 'Extract' type class if there is no match.
-  These are defined in each backend module, but documented here for convenience.
-
-
-@ RegexContext a b (MatchOffset,MatchLength) @ :
-  This returns the initial index and length of the whole match.
-  MatchLength will always be non-negative, and 0 for a failed match.
-
-
-@ RegexContext a b (MatchResult b) @ : The
-  'MatchResult' structure with details for the match.  This is the
-  structure copied from the old @JRegex@ pacakge.
-
-
-@ RegexContext a b (b, b, b) @ :
-  The text before the match, the text of the match, the text after the match
-
-
-@ RegexContext a b (b, MatchText b, b) @ :
-  The text before the match, the details of the match, and the text after the match
-
-
-@ RegexContext a b (b, b, b, [b]) @ : 
-  The text before the match, the text of the match, the text after the
-  match, and a list of the text of the 1st and higher sub-parts of the
-  match.  This is the same return value as used in the old
-  @Text.Regex@ API.
-
-Two containers of the submatch offset information:
-
-
-@ RegexContext a b MatchArray @ :
-  Array of @(MatchOffset,MatchLength)@ for all the sub matches.
-  The whole match is at the intial 0th index.
-  Noncaptured submatches will have a @MatchOffset@ of (-1)
-  The array will have no elements and bounds (1,0) if there is no match.
-
-
-@ RegexContext a b (AllSubmatches [] (MatchOffset,MatchLength) @ :
-  List of @(MatchOffset,MatchLength)@
-  The whole match is the first element, the rest are the submatches (if any) in order.
-  The list is empty if there is no match.
-
-Two containers of the submatch text and offset information:
-
-@ RegexContext a b (AllTextSubmatches (Array Int) (b, (MatchOffset, MatchLength))) @
-
-@ RegexContext a b (AllTextSubmatches [] (b, (MatchOffset, MatchLength)))  @
-
-Two containers of the submatch text information:
-
-@ RegexContext a b (AllTextSubmatches [] b) @
-
-@ RegexContext a b (AllTextSubmatches (Array Int) b) @
-
-These instances are for all the matches (non-overlapping).  Note that
-backends are supposed to supply 'RegexLike' instances for which the
-default 'matchAll' and 'matchAllText' stop searching after returning
-any successful but empty match.
-
-
-@ RegexContext a b Int @ :
-  The number of matches, non-negative.
-
-Two containers for locations of all matches:
-
-@ RegexContext a b (AllMatches [] (MatchOffset, MatchLength)) @
-
-@ RegexContext a b (AllMatches (Array Int) (MatchOffset,MatchLength)) @
-
-Two containers for the locations of all matches and their submatches:
-
-@ RegexContext a b [MatchArray] @ :
-
-@ RegexContext a b (AllMatches (Array Int) MatchArray) @
-
-Two containers for the text and locations of all matches and their submatches:
-
-@ RegexContext a b [MatchText b] @
-
-@ RegexContext a b (AllTextMatches (Array Int) (MatchText b)) @
-
-Two containers for text of all matches:
-@ RegexContext a b (AllTextMatches [] b) @
-
-@ RegexContext a b (AllTextMatches (Array Int) b) @
-
-Four containers for text of all matches and their submatches:
-
-@ RegexContext a b [[b]] @
-
-@ RegexContext a b (AllTextMatches (Array Int) [b]) @
-
-@ RegexContext a b (AllTextMatches [] (Array Int b)) @
-
-@ RegexContext a b (AllTextMatches (Array Int) (Array Int b)) @
-
-Unused matches are 'empty' (defined via 'Extract')
-
--}
-
-module Text.Regex.Base.Context() where
-
-import Control.Monad(liftM)
-import Data.Array(Array,(!),elems,listArray)
---  import Data.Maybe(maybe)
-import Text.Regex.Base.RegexLike(RegexLike(..),RegexContext(..)
-  ,AllSubmatches(..),AllTextSubmatches(..),AllMatches(..),AllTextMatches(..)
-  ,MatchResult(..),Extract(empty),MatchOffset,MatchLength,MatchArray,MatchText)
-
-
-{-
--- Get the ByteString type for mood/doom
-import Data.ByteString(ByteString)
--- Get the Regex types for the mood/doom workaround
-import qualified Text.Regex.Lib.WrapPosix as R1(Regex)
-import qualified Text.Regex.Lib.WrapPCRE as R2(Regex)
-import qualified Text.Regex.Lib.WrapLazy as R3(Regex)
-import qualified Text.Regex.Lib.WrapDFAEngine as R4(Regex)
--- Get the RegexLike instances
-import Text.Regex.Lib.StringPosix()
-import Text.Regex.Lib.StringPCRE()
-import Text.Regex.Lib.StringLazy()
-import Text.Regex.Lib.StringDFAEngine()
-import Text.Regex.Lib.ByteStringPosix()
-import Text.Regex.Lib.ByteStringPCRE()
-import Text.Regex.Lib.ByteStringLazy()
-import Text.Regex.Lib.ByteStringDFAEngine()
--}
-{-
-
-mood :: (RegexLike a b) => a -> b -> b
-{-# INLINE mood #-}
-mood r s = case matchOnceText r s of
-    Nothing -> empty
-    Just (_,ma,_) -> fst (ma!0)
-
-doom :: (RegexLike a b,Monad m) => a -> b -> m b
-{-# INLINE doom #-}
-doom =  actOn (\(_,ma,_)->fst (ma!0))
-
-{- These run afoul of various restrictions if I say
-   "instance RegexContext a b b where"
-   so I am listing these cases explicitly
--}
-
-instance RegexContext R1.Regex String String where match = mood; matchM = doom
-instance RegexContext R2.Regex String String where match = mood; matchM = doom
-instance RegexContext R3.Regex String String where match = mood; matchM = doom
-instance RegexContext R4.Regex String String where match = mood; matchM = doom
-instance RegexContext R1.Regex ByteString ByteString where match = mood; matchM = doom
-instance RegexContext R2.Regex ByteString ByteString where match = mood; matchM = doom
-instance RegexContext R3.Regex ByteString ByteString where match = mood; matchM = doom
-instance RegexContext R4.Regex ByteString ByteString where match = mood; matchM = doom
--}
-
-
-nullArray :: Array Int a
-{-# INLINE nullArray #-}
-nullArray = listArray (1,0) []
-
-nullFail :: (RegexContext regex source (AllMatches [] target),Monad m) => regex -> source -> m (AllMatches [] target)
-{-# INLINE nullFail #-}
-nullFail r s = case match r s of
-                 (AllMatches []) -> regexFailed
-                 xs -> return xs
-
-nullFailText :: (RegexContext regex source (AllTextMatches [] target),Monad m) => regex -> source -> m (AllTextMatches [] target)
-{-# INLINE nullFailText #-}
-nullFailText r s = case match r s of
-                     (AllTextMatches []) -> regexFailed
-                     xs -> return xs
-
-nullFail' :: (RegexContext regex source ([] target),Monad m) => regex -> source -> m ([] target)
-{-# INLINE nullFail' #-}
-nullFail' r s = case match r s of
-                 ([]) -> regexFailed
-                 xs -> return xs
-
-regexFailed :: (Monad m) => m b
-{-# INLINE regexFailed #-}
-regexFailed =  fail $ "regex failed to match"
-
-actOn :: (RegexLike r s,Monad m) => ((s,MatchText s,s)->t) -> r -> s -> m t
-{-# INLINE actOn #-}
-actOn f r s = case matchOnceText r s of
-    Nothing -> regexFailed
-    Just preMApost -> return (f preMApost)
-
--- ** Instances based on matchTest ()
-
-instance (RegexLike a b) => RegexContext a b Bool where 
-  match = matchTest
-  matchM r s = case match r s of
-                 False -> regexFailed
-                 True -> return True
-
-instance (RegexLike a b) => RegexContext a b () where
-  match _ _ = ()
-  matchM r s = case matchTest r s of
-                 False -> regexFailed
-                 True -> return ()
-
--- ** Instance based on matchCount
-
-instance (RegexLike a b) => RegexContext a b Int where
-  match = matchCount
-  matchM r s = case match r s of
-                 0 -> regexFailed
-                 x -> return x
-
--- ** Instances based on matchOnce,matchOnceText
-
-instance (RegexLike a b) => RegexContext a b (MatchOffset,MatchLength) where 
-  match r s = maybe (-1,0) (!0) (matchOnce r s)
-  matchM r s = maybe regexFailed (return.(!0)) (matchOnce r s)
-
-instance (RegexLike a b) => RegexContext a b (MatchResult b) where 
-  match r s = maybe (MR {mrBefore = s,mrMatch = empty,mrAfter = empty
-                        ,mrSubs = nullArray,mrSubList = []}) id (matchM r s)
-  matchM = actOn (\(pre,ma,post) -> 
-     let ((whole,_):subs) = elems ma
-     in MR { mrBefore = pre
-           , mrMatch = whole
-           , mrAfter = post
-           , mrSubs = fmap fst ma
-           , mrSubList = map fst subs })
-
-instance (RegexLike a b) => RegexContext a b (b,MatchText b,b) where 
-  match r s = maybe (s,nullArray,empty) id (matchOnceText r s)
-  matchM r s = maybe regexFailed return (matchOnceText r s)
-
-instance (RegexLike a b) => RegexContext a b (b,b,b) where 
-  match r s = maybe (s,empty,empty) id (matchM r s)
-  matchM = actOn (\(pre,ma,post) -> let ((whole,_):_) = elems ma
-                                    in (pre,whole,post))
-
-instance (RegexLike a b) => RegexContext a b (b,b,b,[b]) where 
-  match r s = maybe (s,empty,empty,[]) id (matchM r s)
-  matchM = actOn (\(pre,ma,post) -> let ((whole,_):subs) = elems ma
-                                    in (pre,whole,post,map fst subs))
-
--- now AllSubmatches wrapper
-instance (RegexLike a b) => RegexContext a b MatchArray where 
-  match r s = maybe nullArray id (matchOnce r s)
-  matchM r s = maybe regexFailed return (matchOnce r s)
-instance (RegexLike a b) => RegexContext a b (AllSubmatches [] (MatchOffset,MatchLength)) where 
-  match r s = maybe (AllSubmatches []) id (matchM r s)
-  matchM r s = case matchOnce r s of
-                 Nothing -> regexFailed
-                 Just ma -> return (AllSubmatches (elems ma))
-
--- essentially AllSubmatches applied to (MatchText b)
-instance (RegexLike a b) => RegexContext a b (AllTextSubmatches (Array Int) (b, (MatchOffset, MatchLength))) where 
-  match r s = maybe (AllTextSubmatches nullArray) id (matchM r s)
-  matchM r s = actOn (\(_,ma,_) -> AllTextSubmatches ma) r s
-instance (RegexLike a b) => RegexContext a b (AllTextSubmatches [] (b, (MatchOffset, MatchLength))) where 
-  match r s = maybe (AllTextSubmatches []) id (matchM r s)
-  matchM r s = actOn (\(_,ma,_) -> AllTextSubmatches (elems ma)) r s
-
-instance (RegexLike a b) => RegexContext a b (AllTextSubmatches [] b) where 
-  match r s = maybe (AllTextSubmatches []) id (matchM r s)
-  matchM r s = liftM AllTextSubmatches $ actOn (\(_,ma,_) -> map fst . elems $ ma) r s
-instance (RegexLike a b) => RegexContext a b (AllTextSubmatches (Array Int) b) where 
-  match r s = maybe (AllTextSubmatches nullArray) id (matchM r s)
-  matchM r s = liftM AllTextSubmatches $ actOn (\(_,ma,_) -> fmap fst ma) r s
-
--- ** Instances based on matchAll,matchAllText
-
-instance (RegexLike a b) => RegexContext a b (AllMatches [] (MatchOffset,MatchLength)) where
-  match r s = AllMatches [ ma!0 | ma <- matchAll r s ]
-  matchM r s = nullFail r s
-instance (RegexLike a b) => RegexContext a b (AllMatches (Array Int) (MatchOffset,MatchLength)) where
-  match r s = maybe (AllMatches nullArray) id (matchM r s)
-  matchM r s = case match r s of
-                 (AllMatches []) -> regexFailed
-                 (AllMatches pairs) -> return . AllMatches . listArray (0,pred $ length pairs) $ pairs
-
--- No AllMatches wrapper
-instance (RegexLike a b) => RegexContext a b [MatchArray] where
-  match = matchAll
-  matchM = nullFail'
-instance (RegexLike a b) => RegexContext a b (AllMatches (Array Int) MatchArray) where
-  match r s = maybe (AllMatches nullArray) id (matchM r s)
-  matchM r s = case match r s of
-                 [] -> regexFailed
-                 mas -> return . AllMatches . listArray (0,pred $ length mas) $ mas
-
--- No AllTextMatches wrapper
-instance (RegexLike a b) => RegexContext a b [MatchText b] where
-  match = matchAllText
-  matchM = nullFail'
-instance (RegexLike a b) => RegexContext a b (AllTextMatches (Array Int) (MatchText b)) where
-  match r s = maybe (AllTextMatches nullArray) id (matchM r s)
-  matchM r s = case match r s of
-                 ([]) -> regexFailed
-                 (mts) -> return . AllTextMatches . listArray (0,pred $ length mts) $ mts
-
-instance (RegexLike a b) => RegexContext a b (AllTextMatches [] b) where
-  match r s = AllTextMatches [ fst (ma!0) | ma <- matchAllText r s ]
-  matchM r s = nullFailText r s
-instance (RegexLike a b) => RegexContext a b (AllTextMatches (Array Int) b) where
-  match r s = maybe (AllTextMatches nullArray) id (matchM r s)
-  matchM r s = case match r s of
-                 (AllTextMatches []) -> regexFailed
-                 (AllTextMatches bs) -> return . AllTextMatches . listArray (0,pred $ length bs) $ bs
-
--- No AllTextMatches wrapper
-instance (RegexLike a b) => RegexContext a b [[b]] where
-  match r s = [ map fst (elems ma) | ma <- matchAllText r s ]
-  matchM r s = nullFail' r s
-instance (RegexLike a b) => RegexContext a b (AllTextMatches (Array Int) [b]) where
-  match r s = maybe (AllTextMatches nullArray) id (matchM r s)
-  matchM r s = case match r s of
-                 ([]) -> regexFailed
-                 (ls) -> return . AllTextMatches . listArray (0,pred $ length ls) $ ls
-instance (RegexLike a b) => RegexContext a b (AllTextMatches [] (Array Int b)) where
-  match r s = AllTextMatches [ fmap fst ma | ma <- matchAllText r s ]
-  matchM r s = nullFailText r s
-instance (RegexLike a b) => RegexContext a b (AllTextMatches (Array Int) (Array Int b)) where
-  match r s = maybe (AllTextMatches nullArray) id (matchM r s)
-  matchM r s = case match r s of
-                 (AllTextMatches []) -> regexFailed
-                 (AllTextMatches as) -> return . AllTextMatches . listArray (0,pred $ length as) $ as
diff --git a/Text/Regex/Base/Impl.hs b/Text/Regex/Base/Impl.hs
deleted file mode 100644
--- a/Text/Regex/Base/Impl.hs
+++ /dev/null
@@ -1,58 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Text.Regex.Impl
--- Copyright   :  (c) Chris Kuklewicz 2006
--- License     :  BSD-style (see the file LICENSE)
--- 
--- Maintainer  :  libraries@haskell.org, textregexlazy@personal.mightyreason.com
--- Stability   :  experimental
--- Portability :  non-portable (Text.Regex.Base needs MPTC+FD)
--- 
--- Helper functions for defining certain instances of
--- RegexContext. These help when defining instances of RegexContext
--- with repeated types:
--- 
--- @
--- instance (RegexLike regex source) => RegexContext regex source source where
--- @
--- 
--- runs into overlapping restrictions. To avoid this I have each backend
--- define, for its own Regex type:
--- 
--- @
--- instance RegexContext Regex String String where
---   match = polymatch
---   matchM = polymatchM
--- @
--- 
--- @
--- instance RegexContext Regex ByteString ByteString where
---   match = polymatch
---   matchM = polymatchM
--- @
--------------------------------------------------------------------------------
-
-module Text.Regex.Base.Impl(polymatch,polymatchM) where
-
-import Text.Regex.Base
-import Data.Array((!))
-
-regexFailed :: (Monad m) => m b
-{-# INLINE regexFailed #-}
-regexFailed =  fail $ "regex failed to match"
-
-actOn :: (RegexLike r s,Monad m) => ((s,MatchText s,s)->t) -> r -> s -> m t
-{-# INLINE actOn #-}
-actOn f r s = case matchOnceText r s of
-    Nothing -> regexFailed
-    Just preMApost -> return (f preMApost)
-
-polymatch :: (RegexLike a b) => a -> b -> b
-{-# INLINE polymatch #-}
-polymatch r s = case matchOnceText r s of
-    Nothing -> empty
-    Just (_,ma,_) -> fst (ma!0)
-
-polymatchM :: (RegexLike a b,Monad m) => a -> b -> m b
-{-# INLINE polymatchM #-}
-polymatchM =  actOn (\(_,ma,_)->fst (ma!0))
diff --git a/Text/Regex/Base/RegexLike.hs b/Text/Regex/Base/RegexLike.hs
deleted file mode 100644
--- a/Text/Regex/Base/RegexLike.hs
+++ /dev/null
@@ -1,228 +0,0 @@
-{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies #-}
------------------------------------------------------------------------------
--- |
--- Module      :  Text.Regex.Base.RegexLike
--- Copyright   :  (c) Chris Kuklewicz 2006
--- License     :  BSD-style (see the file LICENSE)
--- 
--- Maintainer  :  libraries@haskell.org, textregexlazy@personal.mightyreason.com
--- Stability   :  experimental
--- Portability :  non-portable (MPTC+FD)
---
--- Classes and instances for Regex matching.
---
--- 
--- All the classes are declared here, and some common type aliases, and
--- the MatchResult data type.
--- 
--- The only instances here are for Extract String and Extract ByteString.
--- There are no data values.  The 'RegexContext' instances are in
--- "Text.Regex.Base.Context", except for ones which run afoul of a
--- repeated variable (RegexContext regex a a), which are defined in each
--- modules' String and ByteString modules.
------------------------------------------------------------------------------
-
-module Text.Regex.Base.RegexLike (
-  -- ** Type aliases
-  MatchOffset,
-  MatchLength,
-  MatchArray,
-  MatchText,
-  -- ** Data types
-  MatchResult(..),
-  -- ** Classes
-  RegexOptions(..),
-  RegexMaker(..),
-  RegexLike(..),
-  RegexContext(..),
-  Extract(..),
-  AllSubmatches(..),AllTextSubmatches(..),AllMatches(..),AllTextMatches(..)
-  ) where
-
-import Data.Array(Array,(!))
-import Data.Maybe(isJust)
-import qualified Data.ByteString as B (take,drop,empty,ByteString)
-import qualified Data.ByteString.Lazy as L (take,drop,empty,ByteString)
-import qualified Data.Sequence as S(take,drop,empty,Seq)
-
--- | 0 based index from start of source, or (-1) for unused
-type MatchOffset = Int
--- | non-negative length of a match
-type MatchLength = Int
--- | 0 based array, with 0th index indicating the full match.  If the
--- full match location is not available, represent as (0,0).
-type MatchArray = Array Int (MatchOffset,MatchLength)
-type MatchText source = Array Int (source,(MatchOffset,MatchLength))
-
--- | This is the same as the type from JRegex.
-data MatchResult a = MR {
-    mrBefore :: a,
-    mrMatch  :: a,
-    mrAfter  :: a,
-    mrSubList :: [a],
-    mrSubs   :: Array Int a
-}
-
-----------------
--- | Rather than carry them around spearately, the options for how to
--- execute a regex are kept as part of the regex.  There are two types
--- of options.  Those that can only be specified at compilation time
--- and never changed are CompOpt.  Those that can be changed later and
--- affect how matching is performed are ExecOpt.  The actually types
--- for these depend on the backend.
-class RegexOptions regex compOpt execOpt 
-  | regex->compOpt execOpt, compOpt->regex execOpt, execOpt->regex compOpt where
-  blankCompOpt :: compOpt    -- ^ no options set at all in the backend
-  blankExecOpt :: execOpt    -- ^ no options set at all in the backend
-  defaultCompOpt :: compOpt  -- ^ reasonable options (extended,caseSensitive,multiline regex)
-  defaultExecOpt :: execOpt  -- ^ reasonable options (extended,caseSensitive,multiline regex)
-  setExecOpts :: execOpt -> regex -> regex
-  -- ^ forget old flags and use new ones
-  getExecOpts :: regex -> execOpt
-  -- ^ retrieve the current flags
-
-----------------
--- | RegexMaker captures the creation of the compiled regular
--- expression from a source type and an option type.  'makeRegexM' and
--- 'makeRegexM' report parse error using 'MonadError', usually (Either
--- String regex).
--- 
--- The 'makeRegex' function has a default implementation that depends
--- on makeRegexOpts and used 'defaultCompOpt' and 'defaultExecOpt'.
--- Similarly for 'makeRegexM' and 'makeRegexOptsM'.
---
--- There are also default implementaions for 'makeRegexOpts' and
--- 'makeRegexOptsM' in terms of each other.  So a minimal instance
--- definition needs to only define one of these, hopefully
--- 'makeRegexOptsM'.
-class (RegexOptions regex compOpt execOpt) => RegexMaker regex compOpt execOpt source 
-  | regex -> compOpt execOpt, compOpt -> regex execOpt, execOpt -> regex compOpt where
-  -- | make using the defaultCompOpt and defaultExecOpt
-  makeRegex :: source -> regex
-  -- | Specify your own options
-  makeRegexOpts :: compOpt -> execOpt -> source -> regex
-  -- | make using the defaultCompOpt and defaultExecOpt, reporting errors with fail
-  makeRegexM :: (Monad m) => source -> m regex
-  -- | Specify your own options, reporting errors with fail
-  makeRegexOptsM :: (Monad m) => compOpt -> execOpt -> source -> m regex
-
-  makeRegex = makeRegexOpts defaultCompOpt defaultExecOpt
-  makeRegexM = makeRegexOptsM defaultCompOpt defaultExecOpt
-  makeRegexOpts c e s = maybe (error "makeRegexOpts failed") id (makeRegexOptsM c e s)
-  makeRegexOptsM c e s = return (makeRegexOpts c e s)
-
-----------------
--- | RegexLike is parametrized on a regular expression type and a
--- source type to run the matching on.
---
--- There are default implementations: matchTest and matchOnceText use
--- matchOnce; matchCount and matchAllText use matchAll. matchOnce uses
--- matchOnceText and matchAll uses matchAllText. So a minimal complete
--- instance need to provide at least (matchOnce or matchOnceText) and
--- (matchAll or matchAllText).  Additional definitions are often
--- provided where they will increase efficiency.
---
--- > [ c | let notVowel = makeRegex "[^aeiou]" :: Regex, c <- ['a'..'z'], matchTest notVowel [c]  ]
--- >
--- > "bcdfghjklmnpqrstvwxyz"
---
--- The strictness of these functions is instance dependent.
-class (Extract source)=> RegexLike regex source where
-  -- | This returns the first match in the source (it checks the whole
-  -- source, not just at the start). This returns an array of
-  -- (offset,length) index pairs for the match and captured
-  -- substrings.  The offset is 0-based.  A (-1) for an offset means a
-  -- failure to match.  The lower bound of the array is 0, and the 0th
-  -- element is the (offset,length) for the whole match.
-  matchOnce  :: regex -> source-> Maybe MatchArray
-  -- | matchAll returns a list of matches.  The matches are in order
-  -- and do not overlap. If any match succeeds but has 0 length then
-  -- this will be the last match in the list.
-  matchAll   :: regex -> source-> [MatchArray]
-  -- | matchCount returns the number of non-overlapping matches
-  -- returned by matchAll.
-  matchCount :: regex -> source-> Int
-  -- | matchTest return True if there is a match somewhere in the
-  -- source (it checks the whole source not just at the start).
-  matchTest  :: regex -> source-> Bool
-  -- | This is matchAll with the actual subsections of the source
-  -- instead of just the (offset,length) information.
-  matchAllText  :: regex -> source-> [MatchText source]
-  -- | This can return a tuple of three items: the source before the
-  -- match, an array of the match and captured substrings (with their
-  -- indices), and the source after the match.
-  matchOnceText :: regex -> source-> Maybe (source,MatchText source,source)
-
-  matchAll regex source = map (fmap snd) (matchAllText regex source)
-  matchOnce regex source = fmap (\(_,mt,_) -> fmap snd mt) (matchOnceText regex source)
-  matchTest regex source = isJust (matchOnce regex source)
-  matchCount regex source = length (matchAll regex source)
-  matchOnceText regex source = 
-    fmap (\ma -> let (o,l) = ma!0
-                 in (before o source
-                    ,fmap (\ol -> (extract ol source,ol)) ma
-                    ,after (o+l) source))
-         (matchOnce regex source)
-  matchAllText regex source =
-    map (fmap (\ol -> (extract ol source,ol)))
-        (matchAll regex source)
-
-----------------
--- | RegexContext is the polymorphic interface to do matching.  Since
--- 'target' is polymorphic you may need to suply the type explicitly
--- in contexts where it cannot be inferred.
---
--- The monadic 'matchM' version uses 'fail' to report when the 'regex'
--- has no match in 'source'.  Two examples:
---
--- Here the contest 'Bool' is inferred:
---
--- > [ c | let notVowel = makeRegex "[^aeiou]" :: Regex, c <- ['a'..'z'], match notVowel [c]  ]
--- >
--- > "bcdfghjklmnpqrstvwxyz"
---
--- Here the context '[String]' must be supplied:
---
--- > let notVowel = (makeRegex "[^aeiou]" :: Regex )
--- > in do { c <- ['a'..'z'] ; matchM notVowel [c] } :: [String]
--- >
--- > ["b","c","d","f","g","h","j","k","l","m","n","p","q","r","s","t","v","w","x","y","z"]
-class (RegexLike regex source) => RegexContext regex source target where
-  match :: regex -> source -> target
-  matchM :: (Monad m) => regex -> source -> m target
-
-----------------
--- | Extract allows for indexing operations on String or ByteString.
-class Extract source where
-  -- | before is a renamed "take"
-  before :: Int -> source -> source
-  -- | after is a renamed "drop"
-  after :: Int -> source -> source
-  -- | For when there is no match, this can construct an empty data value
-  empty :: source
-  -- | extract takes an offset and length and has a default
-  -- implementation of @extract (off,len) source = before len (after
-  -- off source)@
-  extract :: (Int,Int) -> source -> source
-  extract (off,len) source = before len (after off source)
-
-instance Extract String where
-  before =  take; after = drop; empty = []
-
-instance Extract B.ByteString where
-  before = B.take; after = B.drop; empty = B.empty
-
-instance Extract L.ByteString where
-  before = L.take . toEnum; after = L.drop . toEnum; empty = L.empty
-
-instance Extract (S.Seq a) where
-  before = S.take; after = S.drop; empty = S.empty
-
--- | Used in results of RegexContext instances
-newtype AllSubmatches f b = AllSubmatches {getAllSubmatches :: (f b)}
--- | Used in results of RegexContext instances
-newtype AllTextSubmatches f b = AllTextSubmatches {getAllTextSubmatches :: (f b)}
--- | Used in results of RegexContext instances
-newtype AllMatches f b = AllMatches {getAllMatches :: (f b)}
--- | Used in results of RegexContext instances
-newtype AllTextMatches f b = AllTextMatches {getAllTextMatches :: (f b) }
diff --git a/regex-base.cabal b/regex-base.cabal
--- a/regex-base.cabal
+++ b/regex-base.cabal
@@ -1,58 +1,72 @@
-Name:                   regex-base
--- Keep the version below in sync with ./Text/Regex/Base.hs value getVersion_Text_Regex_Base :: Version
-Version:                0.93.2
-Cabal-Version:          >=1.2
-License:                BSD3
-License-File:           LICENSE
-Copyright:              Copyright (c) 2006, Christopher Kuklewicz
-Author:                 Christopher Kuklewicz
-Maintainer:             TextRegexLazy@personal.mightyreason.com
-Stability:              Seems to work, passes a few tests
-Homepage:               http://sourceforge.net/projects/lazy-regex
-Package-URL:            http://darcs.haskell.org/packages/regex-unstable/regex-base/
-Synopsis:               Replaces/Enhances Text.Regex
-Description:            Interface API for regex-posix,pcre,parsec,tdfa,dfa
-Category:               Text
-Tested-With:            GHC
+cabal-version:          1.12
+name:                   regex-base
+version:                0.94.0.0
+
 build-type:             Simple
-flag newBase
-  description: Choose base >= 4
-  default: True
-flag splitBase
-  description: Choose the new smaller, split-up base package.
-  default: True
+license:                BSD3
+license-file:           LICENSE
+copyright:              Copyright (c) 2006, Christopher Kuklewicz
+author:                 Christopher Kuklewicz
+maintainer:             hvr@gnu.org
+homepage:               https://wiki.haskell.org/Regular_expressions
+bug-reports:            https://github.com/hvr/regex-base/issues
+synopsis:               Common "Text.Regex.*" API for Regex matching
+category:               Text
+description:
+  This package doesn't provide the ability to do regex matching, but instead provides the type-classes that constitute the abstract API that is implemented by @regex-*@ backends such as
+  .
+  * <//hackage.haskell.org/package/regex-posix regex-posix>
+  .
+  * <//hackage.haskell.org/package/regex-parsec regex-parsec>
+  .
+  * <//hackage.haskell.org/package/regex-dfa regex-dfa>
+  .
+  * <//hackage.haskell.org/package/regex-tdfa regex-tdfa>
+  .
+  * <//hackage.haskell.org/package/regex-pcre regex-pcre>
+  .
+  See also <https://wiki.haskell.org/Regular_expressions> for more information.
+
+extra-source-files:
+  ChangeLog.md
+
+source-repository head
+  type:     git
+  location: https://github.com/hvr/regex-base.git
+
 library
-  if flag(newBase)
-    Build-Depends:      base >=4 && < 5, mtl, containers, bytestring, array
-    Extensions:         MultiParamTypeClasses, FunctionalDependencies, TypeSynonymInstances, FlexibleInstances, FlexibleContexts
-  else
-    if flag(splitBase)
-      Build-Depends:      base >= 3.0, mtl, containers, bytestring, array
-      Extensions:         MultiParamTypeClasses, FunctionalDependencies, TypeSynonymInstances, FlexibleInstances, FlexibleContexts
-    else
-      Build-Depends:      base < 3.0, mtl
-      Extensions:         MultiParamTypeClasses, FunctionalDependencies
-  -- Data-Files:
-  -- Extra-Source-Files:
-  -- Extra-Tmp-Files:
-  Exposed-Modules:        Text.Regex.Base
-                          Text.Regex.Base.RegexLike
-                          Text.Regex.Base.Context
-                          Text.Regex.Base.Impl
-  Buildable:              True
-  -- Other-Modules:
-  -- HS-Source-Dirs:         "."
-  GHC-Options:            -Wall -O2
-  -- GHC-Options:            -Wall -Werror -O2
-  -- GHC-Options:            -Wall -ddump-minimal-GHC
-  -- imports-Prof-Options:       -auto-all
-  -- Hugs-Options:
-  -- NHC-Options:
-  -- Includes:
-  -- Include-Dirs:
-  -- C-Sources:
-  -- Extra-Libraries:
-  -- Extra-Lib-Dirs:
-  -- CC-Options:
-  -- LD-Options:
-  -- Frameworks:
+  hs-source-dirs: src
+
+  exposed-modules:
+      Text.Regex.Base
+      Text.Regex.Base.RegexLike
+      Text.Regex.Base.Context
+      Text.Regex.Base.Impl
+
+  other-modules:
+      Paths_regex_base
+
+  default-language: Haskell2010
+  other-extensions:
+      MultiParamTypeClasses
+      FunctionalDependencies
+      TypeSynonymInstances
+      FlexibleInstances
+      FlexibleContexts
+
+  if impl(ghc >= 7.4)
+    default-extensions: Safe
+    build-depends: containers >= 0.4.2.1
+                 , bytestring >= 0.9.2.1
+
+  build-depends: base       >= 4.3 && < 4.14
+               , mtl        >= 1.1 && < 2.3
+               , containers >= 0.4 && < 0.7
+               , bytestring >= 0.9 && < 0.11
+               , array      >= 0.3 && < 0.6
+               , text       >= 1.2.3 && < 1.3
+
+  if !impl(ghc >= 8)
+      build-depends: fail == 4.9.*
+
+  ghc-options: -Wall -O2
diff --git a/src/Text/Regex/Base.hs b/src/Text/Regex/Base.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Regex/Base.hs
@@ -0,0 +1,80 @@
+{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies #-}
+-----------------------------------------------------------------------------
+-- |
+--
+-- Module      :  Text.Regex.Base
+-- Copyright   :  (c) Chris Kuklewicz 2006
+-- SPDX-License-Identifier: BSD-3-Clause
+--
+-- Maintainer  :  hvr@gnu.org
+-- Stability   :  experimental
+-- Portability :  non-portable (MPTC+FD)
+--
+-- Classes and instances for Regex matching.
+--
+--
+-- This module merely imports and re-exports the common part of the new
+-- api: "Text.Regex.Base.RegexLike" and "Text.Regex.Base.Context".
+--
+-- To see what result types the instances of RegexContext can produce,
+-- please read the "Text.Regex.Base.Context" haddock documentation.
+--
+-- This does not provide any of the backends, just the common interface
+-- they all use.  The modules which provide the backends and their cabal
+-- packages are:
+--
+--  * @Text.Regex.Posix@ from regex-posix
+--
+--  * @Text.Regex@ from regex-compat (uses regex-posix)
+--
+--  * @Text.Regex.Parsec@ from regex-parsec
+--
+--  * @Text.Regex.DFA@ from regex-dfa
+--
+--  * @Text.Regex.PCRE@ from regex-pcre
+--
+--  * @Test.Regex.TRE@ from regex-tre
+--
+-- In fact, just importing one of the backends is adequate, you do not
+-- also need to import this module.
+--
+-- == Example
+--
+-- The code below
+--
+-- @
+-- import Text.Regex.Base
+-- import Text.Regex.Posix((=~),(=~~)) -- or DFA or PCRE or PosixRE
+--
+-- main = let b :: Bool
+--            b = ("abaca" =~ "(.)a")
+--            c :: [MatchArray]
+--            c = ("abaca" =~ "(.)a")
+--            d :: Maybe (String,String,String,[String])
+--            d = ("abaca" =~~ "(.)a")
+--        in do print b
+--              print c
+--              print d
+-- @
+--
+-- will output
+--
+-- > True
+-- > [array (0,1) [(0,(1,2)),(1,(1,1))],array (0,1) [(0,(3,2)),(1,(3,1))]]
+-- > Just ("a","ba","ca",["b"])
+--
+
+-----------------------------------------------------------------------------
+
+module Text.Regex.Base (getVersion_Text_Regex_Base
+  -- | RegexLike defines classes and type, and 'Extract' instances
+  ,module Text.Regex.Base.RegexLike) where
+
+import Data.Version(Version(..))
+import Text.Regex.Base.RegexLike
+import Text.Regex.Base.Context()
+
+import qualified Paths_regex_base
+
+getVersion_Text_Regex_Base :: Version
+getVersion_Text_Regex_Base = Paths_regex_base.version
diff --git a/src/Text/Regex/Base/Context.hs b/src/Text/Regex/Base/Context.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Regex/Base/Context.hs
@@ -0,0 +1,412 @@
+{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, FlexibleContexts, TypeSynonymInstances #-}
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+{-|
+
+Module      :  Text.Regex.Base.Context
+Copyright   :  (c) Chris Kuklewicz 2006
+SPDX-License-Identifier: BSD-3-Clause
+
+Maintainer  :  hvr@gnu.org
+Stability   :  experimental
+Portability :  non-portable (MPTC+FD)
+
+This is a module of instances of 'RegexContext' (defined in
+Text.Regex.Base.RegexLike).  Nothing else is exported.  This is
+usually imported via the Text.Regex.Base convenience package which
+itself is re-exported from newer Text.Regex.XXX modules provided by
+the different regex-xxx backends.
+
+These instances work for all the supported types and backends
+interchangably.  These instances provide the different results that
+can be gotten from a match or matchM operation (often via the @=~@ and
+@=~~@ operators with combine @makeRegex@ with @match@ and @matchM@
+respectively).  This module name is Context because they operators are
+context dependent: use them in a context that expects an Int and you
+get a count of matches, use them in a Bool context and get True if
+there is a match, etc.
+
+@RegexContext a b c@ takes a regular expression suppied in a type 'a'
+generated by 'RegexMaker' and a target text supplied in type 'b' to a
+result type 'c' using the 'match' class function.  The 'matchM' class
+function works like 'match' unless there is no match found, in which
+case it calls 'fail' in the (arbitrary) monad context.
+
+There are a few type synonyms from RegexLike that are used here:
+
+@ 
+-- | 0 based index from start of source, or (-1) for unused
+type MatchOffset = Int
+-- | non-negative length of a match
+type MatchLength = Int
+type MatchArray = Array Int (MatchOffset, MatchLength)
+type MatchText source = Array Int (source, (MatchOffset, MatchLength))
+@
+
+There are also a few newtypes that used to prevent any possible
+overlap of types, which were not needed for GHC's late overlap
+detection but are needed for use in Hugs.
+
+@
+newtype AllSubmatches f b = AllSubmatches {getAllSubmatches :: (f b)}
+newtype AllTextSubmatches f b = AllTextSubmatches {getAllTextSubmatches :: (f b)}
+newtype AllMatches f b = AllMatches {getAllMatches :: (f b)}
+newtype AllTextMatches f b = AllTextMatches {getAllTextMatches :: (f b) }
+@
+
+The newtypes' @f@ parameters are the containers, usually @[]@ or
+@Array Int@, (where the arrays all have lower bound 0).
+
+The two *Submatches newtypes return only information on the first
+match.  The other two newtypes return information on all the
+non-overlapping matches.  The two *Text* newtypes are used to mark
+result types that contain the same type as the target text.
+
+Where provided, noncaptured submatches will have a @MatchOffset@ of
+(-1) and non-negative otherwise.  The semantics of submatches depend
+on the backend and its compile and execution options.  Where provided,
+@MatchLength@ will always be non-negative.  Arrays with no elements
+are returned with bounds of (1,0).  Arrays with elements will have a
+lower bound of 0.
+
+XXX THIS HADDOCK DOCUMENTATION IS OUT OF DATE XXX
+
+These are for finding the first match in the target text:
+
+
+@ RegexContext a b Bool @ :
+  Whether there is any match or not.
+
+
+@ RegexContext a b () @ :
+  Useful as a guard with @matchM@ or @=~~@ in a monad, since failure to match calls 'fail'.
+
+
+@ RegexContext a b b @ :
+  This returns the text of the whole match.
+  It will return 'empty' from the 'Extract' type class if there is no match.
+  These are defined in each backend module, but documented here for convenience.
+
+
+@ RegexContext a b (MatchOffset,MatchLength) @ :
+  This returns the initial index and length of the whole match.
+  MatchLength will always be non-negative, and 0 for a failed match.
+
+
+@ RegexContext a b (MatchResult b) @ : The
+  'MatchResult' structure with details for the match.  This is the
+  structure copied from the old @JRegex@ pacakge.
+
+
+@ RegexContext a b (b, b, b) @ :
+  The text before the match, the text of the match, the text after the match
+
+
+@ RegexContext a b (b, MatchText b, b) @ :
+  The text before the match, the details of the match, and the text after the match
+
+
+@ RegexContext a b (b, b, b, [b]) @ : 
+  The text before the match, the text of the match, the text after the
+  match, and a list of the text of the 1st and higher sub-parts of the
+  match.  This is the same return value as used in the old
+  @Text.Regex@ API.
+
+Two containers of the submatch offset information:
+
+
+@ RegexContext a b MatchArray @ :
+  Array of @(MatchOffset,MatchLength)@ for all the sub matches.
+  The whole match is at the intial 0th index.
+  Noncaptured submatches will have a @MatchOffset@ of (-1)
+  The array will have no elements and bounds (1,0) if there is no match.
+
+
+@ RegexContext a b (AllSubmatches [] (MatchOffset,MatchLength) @ :
+  List of @(MatchOffset,MatchLength)@
+  The whole match is the first element, the rest are the submatches (if any) in order.
+  The list is empty if there is no match.
+
+Two containers of the submatch text and offset information:
+
+@ RegexContext a b (AllTextSubmatches (Array Int) (b, (MatchOffset, MatchLength))) @
+
+@ RegexContext a b (AllTextSubmatches [] (b, (MatchOffset, MatchLength)))  @
+
+Two containers of the submatch text information:
+
+@ RegexContext a b (AllTextSubmatches [] b) @
+
+@ RegexContext a b (AllTextSubmatches (Array Int) b) @
+
+These instances are for all the matches (non-overlapping).  Note that
+backends are supposed to supply 'RegexLike' instances for which the
+default 'matchAll' and 'matchAllText' stop searching after returning
+any successful but empty match.
+
+
+@ RegexContext a b Int @ :
+  The number of matches, non-negative.
+
+Two containers for locations of all matches:
+
+@ RegexContext a b (AllMatches [] (MatchOffset, MatchLength)) @
+
+@ RegexContext a b (AllMatches (Array Int) (MatchOffset,MatchLength)) @
+
+Two containers for the locations of all matches and their submatches:
+
+@ RegexContext a b [MatchArray] @ :
+
+@ RegexContext a b (AllMatches (Array Int) MatchArray) @
+
+Two containers for the text and locations of all matches and their submatches:
+
+@ RegexContext a b [MatchText b] @
+
+@ RegexContext a b (AllTextMatches (Array Int) (MatchText b)) @
+
+Two containers for text of all matches:
+@ RegexContext a b (AllTextMatches [] b) @
+
+@ RegexContext a b (AllTextMatches (Array Int) b) @
+
+Four containers for text of all matches and their submatches:
+
+@ RegexContext a b [[b]] @
+
+@ RegexContext a b (AllTextMatches (Array Int) [b]) @
+
+@ RegexContext a b (AllTextMatches [] (Array Int b)) @
+
+@ RegexContext a b (AllTextMatches (Array Int) (Array Int b)) @
+
+Unused matches are 'empty' (defined via 'Extract')
+
+-}
+
+module Text.Regex.Base.Context() where
+
+import Prelude hiding (fail)
+import Control.Monad.Fail (MonadFail(fail)) -- see 'regexFailed'
+
+import Control.Monad(liftM)
+import Data.Array(Array,(!),elems,listArray)
+--  import Data.Maybe(maybe)
+import Text.Regex.Base.RegexLike(RegexLike(..),RegexContext(..)
+  ,AllSubmatches(..),AllTextSubmatches(..),AllMatches(..),AllTextMatches(..)
+  ,MatchResult(..),Extract(empty),MatchOffset,MatchLength,MatchArray,MatchText)
+
+
+{-
+-- Get the ByteString type for mood/doom
+import Data.ByteString(ByteString)
+-- Get the Regex types for the mood/doom workaround
+import qualified Text.Regex.Lib.WrapPosix as R1(Regex)
+import qualified Text.Regex.Lib.WrapPCRE as R2(Regex)
+import qualified Text.Regex.Lib.WrapLazy as R3(Regex)
+import qualified Text.Regex.Lib.WrapDFAEngine as R4(Regex)
+-- Get the RegexLike instances
+import Text.Regex.Lib.StringPosix()
+import Text.Regex.Lib.StringPCRE()
+import Text.Regex.Lib.StringLazy()
+import Text.Regex.Lib.StringDFAEngine()
+import Text.Regex.Lib.ByteStringPosix()
+import Text.Regex.Lib.ByteStringPCRE()
+import Text.Regex.Lib.ByteStringLazy()
+import Text.Regex.Lib.ByteStringDFAEngine()
+-}
+{-
+
+mood :: (RegexLike a b) => a -> b -> b
+{-# INLINE mood #-}
+mood r s = case matchOnceText r s of
+    Nothing -> empty
+    Just (_,ma,_) -> fst (ma!0)
+
+doom :: (RegexLike a b,Monad m) => a -> b -> m b
+{-# INLINE doom #-}
+doom =  actOn (\(_,ma,_)->fst (ma!0))
+
+{- These run afoul of various restrictions if I say
+   "instance RegexContext a b b where"
+   so I am listing these cases explicitly
+-}
+
+instance RegexContext R1.Regex String String where match = mood; matchM = doom
+instance RegexContext R2.Regex String String where match = mood; matchM = doom
+instance RegexContext R3.Regex String String where match = mood; matchM = doom
+instance RegexContext R4.Regex String String where match = mood; matchM = doom
+instance RegexContext R1.Regex ByteString ByteString where match = mood; matchM = doom
+instance RegexContext R2.Regex ByteString ByteString where match = mood; matchM = doom
+instance RegexContext R3.Regex ByteString ByteString where match = mood; matchM = doom
+instance RegexContext R4.Regex ByteString ByteString where match = mood; matchM = doom
+-}
+
+
+nullArray :: Array Int a
+{-# INLINE nullArray #-}
+nullArray = listArray (1,0) []
+
+nullFail :: (RegexContext regex source (AllMatches [] target),MonadFail m) => regex -> source -> m (AllMatches [] target)
+{-# INLINE nullFail #-}
+nullFail r s = case match r s of
+                 (AllMatches []) -> regexFailed
+                 xs -> return xs
+
+nullFailText :: (RegexContext regex source (AllTextMatches [] target),MonadFail m) => regex -> source -> m (AllTextMatches [] target)
+{-# INLINE nullFailText #-}
+nullFailText r s = case match r s of
+                     (AllTextMatches []) -> regexFailed
+                     xs -> return xs
+
+nullFail' :: (RegexContext regex source ([] target),MonadFail m) => regex -> source -> m ([] target)
+{-# INLINE nullFail' #-}
+nullFail' r s = case match r s of
+                 ([]) -> regexFailed
+                 xs -> return xs
+
+regexFailed :: (MonadFail m) => m b
+{-# INLINE regexFailed #-}
+regexFailed =  fail $ "regex failed to match"
+
+actOn :: (RegexLike r s,MonadFail m) => ((s,MatchText s,s)->t) -> r -> s -> m t
+{-# INLINE actOn #-}
+actOn f r s = case matchOnceText r s of
+    Nothing -> regexFailed
+    Just preMApost -> return (f preMApost)
+
+-- ** Instances based on matchTest ()
+
+instance (RegexLike a b) => RegexContext a b Bool where 
+  match = matchTest
+  matchM r s = case match r s of
+                 False -> regexFailed
+                 True -> return True
+
+instance (RegexLike a b) => RegexContext a b () where
+  match _ _ = ()
+  matchM r s = case matchTest r s of
+                 False -> regexFailed
+                 True -> return ()
+
+-- ** Instance based on matchCount
+
+instance (RegexLike a b) => RegexContext a b Int where
+  match = matchCount
+  matchM r s = case match r s of
+                 0 -> regexFailed
+                 x -> return x
+
+-- ** Instances based on matchOnce,matchOnceText
+
+instance (RegexLike a b) => RegexContext a b (MatchOffset,MatchLength) where 
+  match r s = maybe (-1,0) (!0) (matchOnce r s)
+  matchM r s = maybe regexFailed (return.(!0)) (matchOnce r s)
+
+instance (RegexLike a b) => RegexContext a b (MatchResult b) where 
+  match r s = maybe (MR {mrBefore = s,mrMatch = empty,mrAfter = empty
+                        ,mrSubs = nullArray,mrSubList = []}) id (matchM r s)
+  matchM = actOn (\(pre,ma,post) -> 
+     let ((whole,_):subs) = elems ma
+     in MR { mrBefore = pre
+           , mrMatch = whole
+           , mrAfter = post
+           , mrSubs = fmap fst ma
+           , mrSubList = map fst subs })
+
+instance (RegexLike a b) => RegexContext a b (b,MatchText b,b) where 
+  match r s = maybe (s,nullArray,empty) id (matchOnceText r s)
+  matchM r s = maybe regexFailed return (matchOnceText r s)
+
+instance (RegexLike a b) => RegexContext a b (b,b,b) where 
+  match r s = maybe (s,empty,empty) id (matchM r s)
+  matchM = actOn (\(pre,ma,post) -> let ((whole,_):_) = elems ma
+                                    in (pre,whole,post))
+
+instance (RegexLike a b) => RegexContext a b (b,b,b,[b]) where 
+  match r s = maybe (s,empty,empty,[]) id (matchM r s)
+  matchM = actOn (\(pre,ma,post) -> let ((whole,_):subs) = elems ma
+                                    in (pre,whole,post,map fst subs))
+
+-- now AllSubmatches wrapper
+instance (RegexLike a b) => RegexContext a b MatchArray where 
+  match r s = maybe nullArray id (matchOnce r s)
+  matchM r s = maybe regexFailed return (matchOnce r s)
+instance (RegexLike a b) => RegexContext a b (AllSubmatches [] (MatchOffset,MatchLength)) where 
+  match r s = maybe (AllSubmatches []) id (matchM r s)
+  matchM r s = case matchOnce r s of
+                 Nothing -> regexFailed
+                 Just ma -> return (AllSubmatches (elems ma))
+
+-- essentially AllSubmatches applied to (MatchText b)
+instance (RegexLike a b) => RegexContext a b (AllTextSubmatches (Array Int) (b, (MatchOffset, MatchLength))) where 
+  match r s = maybe (AllTextSubmatches nullArray) id (matchM r s)
+  matchM r s = actOn (\(_,ma,_) -> AllTextSubmatches ma) r s
+instance (RegexLike a b) => RegexContext a b (AllTextSubmatches [] (b, (MatchOffset, MatchLength))) where 
+  match r s = maybe (AllTextSubmatches []) id (matchM r s)
+  matchM r s = actOn (\(_,ma,_) -> AllTextSubmatches (elems ma)) r s
+
+instance (RegexLike a b) => RegexContext a b (AllTextSubmatches [] b) where 
+  match r s = maybe (AllTextSubmatches []) id (matchM r s)
+  matchM r s = liftM AllTextSubmatches $ actOn (\(_,ma,_) -> map fst . elems $ ma) r s
+instance (RegexLike a b) => RegexContext a b (AllTextSubmatches (Array Int) b) where 
+  match r s = maybe (AllTextSubmatches nullArray) id (matchM r s)
+  matchM r s = liftM AllTextSubmatches $ actOn (\(_,ma,_) -> fmap fst ma) r s
+
+-- ** Instances based on matchAll,matchAllText
+
+instance (RegexLike a b) => RegexContext a b (AllMatches [] (MatchOffset,MatchLength)) where
+  match r s = AllMatches [ ma!0 | ma <- matchAll r s ]
+  matchM r s = nullFail r s
+instance (RegexLike a b) => RegexContext a b (AllMatches (Array Int) (MatchOffset,MatchLength)) where
+  match r s = maybe (AllMatches nullArray) id (matchM r s)
+  matchM r s = case match r s of
+                 (AllMatches []) -> regexFailed
+                 (AllMatches pairs) -> return . AllMatches . listArray (0,pred $ length pairs) $ pairs
+
+-- No AllMatches wrapper
+instance (RegexLike a b) => RegexContext a b [MatchArray] where
+  match = matchAll
+  matchM = nullFail'
+instance (RegexLike a b) => RegexContext a b (AllMatches (Array Int) MatchArray) where
+  match r s = maybe (AllMatches nullArray) id (matchM r s)
+  matchM r s = case match r s of
+                 [] -> regexFailed
+                 mas -> return . AllMatches . listArray (0,pred $ length mas) $ mas
+
+-- No AllTextMatches wrapper
+instance (RegexLike a b) => RegexContext a b [MatchText b] where
+  match = matchAllText
+  matchM = nullFail'
+instance (RegexLike a b) => RegexContext a b (AllTextMatches (Array Int) (MatchText b)) where
+  match r s = maybe (AllTextMatches nullArray) id (matchM r s)
+  matchM r s = case match r s of
+                 ([]) -> regexFailed
+                 (mts) -> return . AllTextMatches . listArray (0,pred $ length mts) $ mts
+
+instance (RegexLike a b) => RegexContext a b (AllTextMatches [] b) where
+  match r s = AllTextMatches [ fst (ma!0) | ma <- matchAllText r s ]
+  matchM r s = nullFailText r s
+instance (RegexLike a b) => RegexContext a b (AllTextMatches (Array Int) b) where
+  match r s = maybe (AllTextMatches nullArray) id (matchM r s)
+  matchM r s = case match r s of
+                 (AllTextMatches []) -> regexFailed
+                 (AllTextMatches bs) -> return . AllTextMatches . listArray (0,pred $ length bs) $ bs
+
+-- No AllTextMatches wrapper
+instance (RegexLike a b) => RegexContext a b [[b]] where
+  match r s = [ map fst (elems ma) | ma <- matchAllText r s ]
+  matchM r s = nullFail' r s
+instance (RegexLike a b) => RegexContext a b (AllTextMatches (Array Int) [b]) where
+  match r s = maybe (AllTextMatches nullArray) id (matchM r s)
+  matchM r s = case match r s of
+                 ([]) -> regexFailed
+                 (ls) -> return . AllTextMatches . listArray (0,pred $ length ls) $ ls
+instance (RegexLike a b) => RegexContext a b (AllTextMatches [] (Array Int b)) where
+  match r s = AllTextMatches [ fmap fst ma | ma <- matchAllText r s ]
+  matchM r s = nullFailText r s
+instance (RegexLike a b) => RegexContext a b (AllTextMatches (Array Int) (Array Int b)) where
+  match r s = maybe (AllTextMatches nullArray) id (matchM r s)
+  matchM r s = case match r s of
+                 (AllTextMatches []) -> regexFailed
+                 (AllTextMatches as) -> return . AllTextMatches . listArray (0,pred $ length as) $ as
diff --git a/src/Text/Regex/Base/Impl.hs b/src/Text/Regex/Base/Impl.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Regex/Base/Impl.hs
@@ -0,0 +1,67 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Text.Regex.Impl
+-- Copyright   :  (c) Chris Kuklewicz 2006
+-- SPDX-License-Identifier: BSD-3-Clause
+-- 
+-- Maintainer  :  hvr@gnu.org
+-- Stability   :  experimental
+-- Portability :  non-portable (Text.Regex.Base needs MPTC+FD)
+-- 
+-- Helper functions for defining certain instances of
+-- RegexContext. These help when defining instances of RegexContext
+-- with repeated types:
+-- 
+-- @
+-- instance (RegexLike regex source) => RegexContext regex source source where
+-- @
+-- 
+-- runs into overlapping restrictions. To avoid this I have each backend
+-- define, for its own Regex type:
+-- 
+-- @
+-- instance RegexContext Regex String String where
+--   match = polymatch
+--   matchM = polymatchM
+-- @
+-- 
+-- @
+-- instance RegexContext Regex ByteString ByteString where
+--   match = polymatch
+--   matchM = polymatchM
+-- @
+-- 
+-- @
+-- instance RegexContext Regex Text Text where
+--   match = polymatch
+--   matchM = polymatchM
+-- @
+-------------------------------------------------------------------------------
+
+module Text.Regex.Base.Impl(polymatch,polymatchM) where
+
+import Prelude hiding (fail)
+import Control.Monad.Fail (MonadFail(fail))
+
+import Text.Regex.Base
+import Data.Array((!))
+
+regexFailed :: (MonadFail m) => m b
+{-# INLINE regexFailed #-}
+regexFailed =  fail $ "regex failed to match"
+
+actOn :: (RegexLike r s,MonadFail m) => ((s,MatchText s,s)->t) -> r -> s -> m t
+{-# INLINE actOn #-}
+actOn f r s = case matchOnceText r s of
+    Nothing -> regexFailed
+    Just preMApost -> return (f preMApost)
+
+polymatch :: (RegexLike a b) => a -> b -> b
+{-# INLINE polymatch #-}
+polymatch r s = case matchOnceText r s of
+    Nothing -> empty
+    Just (_,ma,_) -> fst (ma!0)
+
+polymatchM :: (RegexLike a b,MonadFail m) => a -> b -> m b
+{-# INLINE polymatchM #-}
+polymatchM =  actOn (\(_,ma,_)->fst (ma!0))
diff --git a/src/Text/Regex/Base/RegexLike.hs b/src/Text/Regex/Base/RegexLike.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Regex/Base/RegexLike.hs
@@ -0,0 +1,240 @@
+{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances, TypeSynonymInstances #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Text.Regex.Base.RegexLike
+-- Copyright   :  (c) Chris Kuklewicz 2006
+-- SPDX-License-Identifier: BSD-3-Clause
+--
+-- Maintainer  :  hvr@gnu.org
+-- Stability   :  experimental
+-- Portability :  non-portable (MPTC+FD)
+--
+-- Classes and instances for Regex matching.
+--
+-- All the classes are declared here, and some common type aliases, and
+-- the MatchResult data type.
+--
+-- The only instances here are for 'Extract' 'String', 'Extract' 'SB.ByteString',
+-- and 'Extract' 'ST.Text'. There are no data values.  The 'RegexContext'
+-- instances are in "Text.Regex.Base.Context", except for ones which
+-- run afoul of a repeated variable ('RegexContext' regex a a), which
+-- are defined in each modules' String and ByteString modules.
+-----------------------------------------------------------------------------
+
+module Text.Regex.Base.RegexLike (
+  -- ** Type aliases
+  MatchOffset,
+  MatchLength,
+  MatchArray,
+  MatchText,
+  -- ** Data types
+  MatchResult(..),
+  -- ** Classes
+  RegexOptions(..),
+  RegexMaker(..),
+  RegexLike(..),
+  RegexContext(..),
+  Extract(..),
+  AllSubmatches(..),AllTextSubmatches(..),AllMatches(..),AllTextMatches(..)
+  ) where
+
+import Prelude hiding (fail)
+import Control.Monad.Fail as Fail (MonadFail)
+
+import Data.Array(Array,(!))
+import Data.Maybe(isJust)
+import qualified Data.ByteString as SB (take,drop,empty,ByteString)
+import qualified Data.ByteString.Lazy as LB (take,drop,empty,ByteString)
+import qualified Data.Sequence as S(take,drop,empty,Seq)
+import qualified Data.Text as ST (take,drop,empty,Text)
+import qualified Data.Text.Lazy as LT (take,drop,empty,Text)
+
+-- | 0 based index from start of source, or (-1) for unused
+type MatchOffset = Int
+-- | non-negative length of a match
+type MatchLength = Int
+-- | 0 based array, with 0th index indicating the full match.  If the
+-- full match location is not available, represent as (0,0).
+type MatchArray = Array Int (MatchOffset,MatchLength)
+type MatchText source = Array Int (source,(MatchOffset,MatchLength))
+
+-- | This is the same as the type from JRegex.
+data MatchResult a = MR {
+    mrBefore :: a,
+    mrMatch  :: a,
+    mrAfter  :: a,
+    mrSubList :: [a],
+    mrSubs   :: Array Int a
+}
+
+----------------
+-- | Rather than carry them around spearately, the options for how to
+-- execute a regex are kept as part of the regex.  There are two types
+-- of options.  Those that can only be specified at compilation time
+-- and never changed are CompOpt.  Those that can be changed later and
+-- affect how matching is performed are ExecOpt.  The actually types
+-- for these depend on the backend.
+class RegexOptions regex compOpt execOpt 
+  | regex->compOpt execOpt, compOpt->regex execOpt, execOpt->regex compOpt where
+  blankCompOpt :: compOpt    -- ^ no options set at all in the backend
+  blankExecOpt :: execOpt    -- ^ no options set at all in the backend
+  defaultCompOpt :: compOpt  -- ^ reasonable options (extended,caseSensitive,multiline regex)
+  defaultExecOpt :: execOpt  -- ^ reasonable options (extended,caseSensitive,multiline regex)
+  setExecOpts :: execOpt -> regex -> regex
+  -- ^ forget old flags and use new ones
+  getExecOpts :: regex -> execOpt
+  -- ^ retrieve the current flags
+
+----------------
+-- | RegexMaker captures the creation of the compiled regular
+-- expression from a source type and an option type.  'makeRegexM' and
+-- 'makeRegexM' report parse error using 'MonadError', usually (Either
+-- String regex).
+-- 
+-- The 'makeRegex' function has a default implementation that depends
+-- on makeRegexOpts and used 'defaultCompOpt' and 'defaultExecOpt'.
+-- Similarly for 'makeRegexM' and 'makeRegexOptsM'.
+--
+-- There are also default implementaions for 'makeRegexOpts' and
+-- 'makeRegexOptsM' in terms of each other.  So a minimal instance
+-- definition needs to only define one of these, hopefully
+-- 'makeRegexOptsM'.
+class (RegexOptions regex compOpt execOpt) => RegexMaker regex compOpt execOpt source 
+  | regex -> compOpt execOpt, compOpt -> regex execOpt, execOpt -> regex compOpt where
+  -- | make using the defaultCompOpt and defaultExecOpt
+  makeRegex :: source -> regex
+  -- | Specify your own options
+  makeRegexOpts :: compOpt -> execOpt -> source -> regex
+  -- | make using the defaultCompOpt and defaultExecOpt, reporting errors with fail
+  makeRegexM :: (Fail.MonadFail m) => source -> m regex
+  -- | Specify your own options, reporting errors with fail
+  makeRegexOptsM :: (MonadFail m) => compOpt -> execOpt -> source -> m regex
+
+  makeRegex = makeRegexOpts defaultCompOpt defaultExecOpt
+  makeRegexM = makeRegexOptsM defaultCompOpt defaultExecOpt
+  makeRegexOpts c e s = maybe (error "makeRegexOpts failed") id (makeRegexOptsM c e s)
+  makeRegexOptsM c e s = return (makeRegexOpts c e s)
+
+----------------
+-- | RegexLike is parametrized on a regular expression type and a
+-- source type to run the matching on.
+--
+-- There are default implementations: matchTest and matchOnceText use
+-- matchOnce; matchCount and matchAllText use matchAll. matchOnce uses
+-- matchOnceText and matchAll uses matchAllText. So a minimal complete
+-- instance need to provide at least (matchOnce or matchOnceText) and
+-- (matchAll or matchAllText).  Additional definitions are often
+-- provided where they will increase efficiency.
+--
+-- > [ c | let notVowel = makeRegex "[^aeiou]" :: Regex, c <- ['a'..'z'], matchTest notVowel [c]  ]
+-- >
+-- > "bcdfghjklmnpqrstvwxyz"
+--
+-- The strictness of these functions is instance dependent.
+class (Extract source)=> RegexLike regex source where
+  -- | This returns the first match in the source (it checks the whole
+  -- source, not just at the start). This returns an array of
+  -- (offset,length) index pairs for the match and captured
+  -- substrings.  The offset is 0-based.  A (-1) for an offset means a
+  -- failure to match.  The lower bound of the array is 0, and the 0th
+  -- element is the (offset,length) for the whole match.
+  matchOnce  :: regex -> source-> Maybe MatchArray
+  -- | matchAll returns a list of matches.  The matches are in order
+  -- and do not overlap. If any match succeeds but has 0 length then
+  -- this will be the last match in the list.
+  matchAll   :: regex -> source-> [MatchArray]
+  -- | matchCount returns the number of non-overlapping matches
+  -- returned by matchAll.
+  matchCount :: regex -> source-> Int
+  -- | matchTest return True if there is a match somewhere in the
+  -- source (it checks the whole source not just at the start).
+  matchTest  :: regex -> source-> Bool
+  -- | This is matchAll with the actual subsections of the source
+  -- instead of just the (offset,length) information.
+  matchAllText  :: regex -> source-> [MatchText source]
+  -- | This can return a tuple of three items: the source before the
+  -- match, an array of the match and captured substrings (with their
+  -- indices), and the source after the match.
+  matchOnceText :: regex -> source-> Maybe (source,MatchText source,source)
+
+  matchAll regex source = map (fmap snd) (matchAllText regex source)
+  matchOnce regex source = fmap (\(_,mt,_) -> fmap snd mt) (matchOnceText regex source)
+  matchTest regex source = isJust (matchOnce regex source)
+  matchCount regex source = length (matchAll regex source)
+  matchOnceText regex source = 
+    fmap (\ma -> let (o,l) = ma!0
+                 in (before o source
+                    ,fmap (\ol -> (extract ol source,ol)) ma
+                    ,after (o+l) source))
+         (matchOnce regex source)
+  matchAllText regex source =
+    map (fmap (\ol -> (extract ol source,ol)))
+        (matchAll regex source)
+
+----------------
+-- | RegexContext is the polymorphic interface to do matching.  Since
+-- 'target' is polymorphic you may need to suply the type explicitly
+-- in contexts where it cannot be inferred.
+--
+-- The monadic 'matchM' version uses 'fail' to report when the 'regex'
+-- has no match in 'source'.  Two examples:
+--
+-- Here the contest 'Bool' is inferred:
+--
+-- > [ c | let notVowel = makeRegex "[^aeiou]" :: Regex, c <- ['a'..'z'], match notVowel [c]  ]
+-- >
+-- > "bcdfghjklmnpqrstvwxyz"
+--
+-- Here the context '[String]' must be supplied:
+--
+-- > let notVowel = (makeRegex "[^aeiou]" :: Regex )
+-- > in do { c <- ['a'..'z'] ; matchM notVowel [c] } :: [String]
+-- >
+-- > ["b","c","d","f","g","h","j","k","l","m","n","p","q","r","s","t","v","w","x","y","z"]
+class (RegexLike regex source) => RegexContext regex source target where
+  match :: regex -> source -> target
+  matchM :: (MonadFail m) => regex -> source -> m target
+
+----------------
+-- | Extract allows for indexing operations on String or ByteString.
+class Extract source where
+  -- | before is a renamed "take"
+  before :: Int -> source -> source
+  -- | after is a renamed "drop"
+  after :: Int -> source -> source
+  -- | For when there is no match, this can construct an empty data value
+  empty :: source
+  -- | extract takes an offset and length and has a default
+  -- implementation of @extract (off,len) source = before len (after
+  -- off source)@
+  extract :: (Int,Int) -> source -> source
+  extract (off,len) source = before len (after off source)
+
+instance Extract String where
+  before =  take; after = drop; empty = []
+
+instance Extract SB.ByteString where
+  before = SB.take; after = SB.drop; empty = SB.empty
+
+instance Extract LB.ByteString where
+  before = LB.take . toEnum; after = LB.drop . toEnum; empty = LB.empty
+
+instance Extract (S.Seq a) where
+  before = S.take; after = S.drop; empty = S.empty
+
+-- | @since 0.94.0.0
+instance Extract ST.Text where
+  before = ST.take; after = ST.drop; empty = ST.empty
+
+-- | @since 0.94.0.0
+instance Extract LT.Text where
+  before = LT.take . toEnum; after = LT.drop . toEnum; empty = LT.empty
+
+-- | Used in results of RegexContext instances
+newtype AllSubmatches f b = AllSubmatches {getAllSubmatches :: (f b)}
+-- | Used in results of RegexContext instances
+newtype AllTextSubmatches f b = AllTextSubmatches {getAllTextSubmatches :: (f b)}
+-- | Used in results of RegexContext instances
+newtype AllMatches f b = AllMatches {getAllMatches :: (f b)}
+-- | Used in results of RegexContext instances
+newtype AllTextMatches f b = AllTextMatches {getAllTextMatches :: (f b) }
