diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -1,3 +1,9 @@
+#####   2.5
+  *API changes*
+  split PCRE to Ascii and Utf8
+  remove \[Comp\] opt from replace signature   
+  tweak trim  
+
 #####   2.4
   refactor Replace: remove ReplaceCase. Use Once | All hints instead  
  
diff --git a/regex-do.cabal b/regex-do.cabal
--- a/regex-do.cabal
+++ b/regex-do.cabal
@@ -1,5 +1,5 @@
 name:                regex-do
-version:             2.4
+version:             2.5
 synopsis:            PCRE wrapper
 description:         format, search, replace (String | ByteString) with PCRE regex. Utf8-safe
 author:              Imants Cekusins
@@ -19,23 +19,28 @@
 library
   exposed-modules:
           Text.Regex.Do.Trim
-          Text.Regex.Do.Pcre.Match
           Text.Regex.Do.Pcre.Option
-          Text.Regex.Do.Pcre.Replace
+          Text.Regex.Do.Pcre.Utf8.Replace
           Text.Regex.Do.Split
           Text.Regex.Do.Format
           Text.Regex.Do.Type.Do
           Text.Regex.Do.Type.Reexport
           Text.Regex.Do.Convert
           Text.Regex.Do.Pad
-          Text.Regex.Do.Pcre.MatchHint
-          Text.Regex.Do.Pcre.ReplaceOpen
+          Text.Regex.Do.Pcre.Ascii.MatchHint
+          Text.Regex.Do.ReplaceOpen
           Text.Regex.Do.Type.Extract
-          Text.Regex.Do.Type.Regex_
+          Text.Regex.Do.Type.Regex
           Text.Regex.Do.Type.MatchHint
-  other-modules:
+          Text.Regex.Do.Pcre.Ascii.Match
+          Text.Regex.Do.Pcre.Ascii.Replace
+          Text.Regex.Do.Pcre.Utf8.Match
+          Text.Regex.Do.Pcre.Utf8.MatchHint
           Text.Regex.Do.Pcre.Matchf
-          Text.Regex.Do.Pcre.Result
+
+  other-modules:
+          Text.Regex.Do.Result
+
   ghc-options:  -fwarn-unused-imports
     
   build-depends:  base <= 5.0,
@@ -58,6 +63,7 @@
                         ConstraintKinds
                         ScopedTypeVariables
                         DeriveFunctor
+                        TypeFamilies
                        
 
 test-suite spec
@@ -74,6 +80,7 @@
                         ConstraintKinds
                         ScopedTypeVariables
                         DeriveFunctor
+                        TypeFamilies
 
 
   main-is: Main.hs
@@ -84,6 +91,7 @@
         TestRegex.TestSplit
         TestRegex.TestTrim
         TestRegex.TestReplaceOpen
+        TestRegex.TestReplaceUtf
 
   build-depends:  base <= 5.0,
                   hspec,
diff --git a/src/Text/Regex/Do/Convert.hs b/src/Text/Regex/Do/Convert.hs
--- a/src/Text/Regex/Do/Convert.hs
+++ b/src/Text/Regex/Do/Convert.hs
@@ -13,6 +13,9 @@
 toByteString::String -> ByteString
 toByteString = E.encodeUtf8 . T.pack
 
+toByteString'::String -> Utf8_ ByteString
+toByteString' = Utf8_ . toByteString
+
 -- | both Ascii and Utf8
 toString::ByteString -> String
 toString = T.unpack . E.decodeUtf8
diff --git a/src/Text/Regex/Do/Pcre/Ascii/Match.hs b/src/Text/Regex/Do/Pcre/Ascii/Match.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Regex/Do/Pcre/Ascii/Match.hs
@@ -0,0 +1,69 @@
+{- | although sometimes funs in Ascii modules work with non-ascii text
+    (as some examples show),
+    for reliable results with Utf8 pattern or body,
+    use "Text.Regex.Do.Pcre.Utf8.Match"
+
+    see also "Text.Regex.Base.RegexLike" and "Text.Regex.Do.Pcre.Ascii.MatchHint" -}
+
+module Text.Regex.Do.Pcre.Ascii.Match
+    (Match(..),
+    R.extract   -- | 'extract' is reexport from "Text.Regex.Base.RegexLike"
+    ) where
+
+import qualified Text.Regex.Base.RegexLike as R hiding (makeRegex)
+import Text.Regex.Do.Type.Do
+import Text.Regex.Do.Pcre.Matchf as F
+import Text.Regex.PCRE.Wrap()
+import Text.Regex.Do.Type.Regex
+import Text.Regex.Do.Type.MatchHint
+
+
+{- | 'match' covers all result types
+
+    compiler looks up the appropriate function depending on the result type
+
+    '=~' is borrowed from "Text.Regex.PCRE.Wrap",
+    is a short version of 'match'
+
+    See also "Text.Regex.Do.Pcre.Ascii.MatchHint"       -}
+
+class Match a b out where
+    match::Pattern a -> Body b -> out
+    (=~)::a     -- ^ pattern
+        -> b    -- ^ body
+        -> out
+    (=~) p0 b0 = match (Pattern p0) (Body b0)
+
+
+-- | match once
+instance Rx_ a b => Match a b [b] where
+    match p0 = once (makeRegex' p0)
+{- ^  >>> "^all" =~ "all the time"::[String]
+
+     \["all"\]      -}
+instance Rx_ a b => Match a b Bool where
+    match p0 (Body b0) = R.matchTest (makeRegex p0) b0
+{- ^ test
+
+    >>> "в" =~ "тихо в лесу"::Bool
+
+    True    -}
+
+-- | match all
+instance Rx_ a b => Match a b [[b]] where
+    match p0 = F.all (makeRegex' p0)
+{- ^  >>> "well" =~ "all is well that ends well"::[[ByteString]]
+
+     \[["well"\],\["well"\]]        -}
+
+-- | match once
+instance Rx_ a b => Match a b [PosLen] where
+    match p0 b0 = maybe [] id $ poslen_ (Once $ makeRegex' p0) b0
+{- ^ >>> "à" =~ "tourner à gauche"::[PosLen]
+
+     \[(8,2)\]      -}
+
+-- | match all
+instance Rx_ a b => Match a b [[PosLen]] where
+    match p0 = poslen_ $ All $ makeRegex' p0
+
diff --git a/src/Text/Regex/Do/Pcre/Ascii/MatchHint.hs b/src/Text/Regex/Do/Pcre/Ascii/MatchHint.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Regex/Do/Pcre/Ascii/MatchHint.hs
@@ -0,0 +1,85 @@
+{- | this module uses
+    <https://cdepillabout.github.io/haskell-type-families-presentation/#/ TypeFamilies>
+
+    this module is similar to "Text.Regex.Do.Pcre.Ascii.Match". The differences are:
+
+    "Text.Regex.Do.Pcre.Ascii.Match" is more flexible:
+        accepts 'Pattern' Regex,
+        accepts 'Pattern' and 'Body' of different types
+
+    "Text.Regex.Do.Pcre.Ascii.Match" needs to infer result type
+
+    in this module the result type is determined by the hint
+    -}
+
+module Text.Regex.Do.Pcre.Ascii.MatchHint where
+
+import Text.Regex.Do.Type.Do hiding (Once,All)
+import Text.Regex.PCRE.Wrap()
+import qualified Text.Regex.Do.Pcre.Ascii.Match as M
+import Text.Regex.Do.Type.MatchHint
+import Data.ByteString
+
+
+{- | picks 'M.Match' instance where 'Pattern' and 'Body' are of the same type
+
+    'Hint' and inferrable 'Pattern' or 'Body' type determine the instance
+
+    handy when working with 'OverloadedStrings', in other cases when compiler needs a hint  -}
+
+
+
+class (Hint hint, M.Match a a (F hint a)) =>
+    MatchHint hint a where
+    type F hint a
+    match::hint (Pattern a) -> Body a -> F hint a
+    match h0 = M.match $ unhint h0
+
+    (=~)::hint a  -- ^ hint & pattern
+            -> a          -- ^ body
+            -> F hint a   -- ^ type defined by the instance, determined by the hint
+    (=~) h0 = (M.=~) $ unhint h0
+
+
+instance MatchHint Test String where
+    type F Test String = Bool
+
+
+instance MatchHint PosLen' String where
+    type F PosLen' String = [PosLen]
+
+{- ^ >>> PosLen' ("и"::String) =~ "бывает и хуже"
+
+    \[(13,2)\]      -}
+
+instance MatchHint PosLen_ String where
+    type F PosLen_ String = [[PosLen]]
+
+instance MatchHint Once String where
+    type F Once String = [String]
+
+{- ^ >>> Once ("^all"::String) =~ "all the time"
+
+    \["all"\]       -}
+
+instance MatchHint All String where
+    type F All String = [[String]]
+
+instance MatchHint Test ByteString where
+    type F Test ByteString = Bool
+
+{- ^ >>> Test ("в"::ByteString) =~ "тихо в лесу"
+
+    True    -}
+
+instance MatchHint PosLen' ByteString where
+    type F PosLen' ByteString = [PosLen]
+
+instance MatchHint PosLen_ ByteString where
+    type F PosLen_ ByteString = [[PosLen]]
+
+instance MatchHint Once ByteString where
+    type F Once ByteString = [ByteString]
+
+instance MatchHint All ByteString where
+    type F All ByteString = [[ByteString]]
diff --git a/src/Text/Regex/Do/Pcre/Ascii/Replace.hs b/src/Text/Regex/Do/Pcre/Ascii/Replace.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Regex/Do/Pcre/Ascii/Replace.hs
@@ -0,0 +1,79 @@
+{- | === Ascii vs Utf8 modules
+
+    for reliable results with Utf8 pattern or body,
+    use "Text.Regex.Do.Pcre.Utf8.Replace"   -}
+
+module Text.Regex.Do.Pcre.Ascii.Replace
+    (Replace(..),
+    Repl_)  where
+
+import Text.Regex.Base.RegexLike as R
+import Prelude as P
+import Text.Regex.Do.Type.Do
+import Text.Regex.Do.Type.Reexport as R
+import Text.Regex.Do.Pcre.Matchf
+import qualified Text.Regex.Do.ReplaceOpen as O
+import Text.Regex.Do.Type.Regex as T
+import Text.Regex.Do.Type.Extract
+import Text.Regex.Do.Type.MatchHint
+import Text.Regex.Do.Pcre.Option as O
+
+
+class Replace all a repl b where
+    replace::(R_ b, Matchf all b) =>
+        all (Pattern a) -> repl b -> Body b -> b
+
+type Repl_ f rx r a = (T.Regex rx,
+                        R.RegexLike R.Regex a,
+                        Extract' a,
+                        O.ReplaceOpen f r)
+
+replace_ fn0 p0 r0 b0 =
+   let ma1 = fn0 p1 b0
+       p1 = T.makeRegex' <$> p0
+   in O.replace ma1 r0 b0
+
+
+
+instance Repl_ Maybe a repl b => Replace Once a repl b where
+    replace = replace_ marray_
+
+{- ^ === static replace for simple (no group) needle
+
+    for no-regex 'ByteString' replacement see "Text.Regex.Do.Split"
+
+    >>> replace (Once (Pattern "^a\\s")) (Replacement "A") (Body "a bc")
+
+    \"Abc\"
+
+   === dynamic group replace
+
+    >>> replace (Once (Pattern "\\w=(\\d{1,3})")) replacer $ Body "a=101 b=3 12"
+
+     "a=[1 0 1] b=3 12"     -}
+
+
+instance Repl_ [] a repl b => Replace All a repl b where
+    replace = replace_ marray_
+
+
+{- ^ to tweak regex with 'O.Comp' or 'O.Exec', see "Text.Regex.Do.Type.Regex"
+
+   === dynamic group replace
+
+   custom replacer fn returns replacement value. See 'O.defaultReplacer'
+
+   >>> replacer::GroupReplacer String
+       replacer = defaultReplacer 1 tweak1
+             where tweak1 str1 = case str1 of
+                                   "101" -> "[1 0 1]"
+                                   "3" -> "[ 3 ]"
+                                   otherwise -> trace str1 "?"
+
+
+    >>> replace (All (Pattern "\\w=(\\d{1,3})")) replacer $ Body "a=101 b=3 12"
+
+        "a=[1 0 1] b=[ 3 ] 12"      -}
+
+dum_::Comp
+dum_ = Blank
diff --git a/src/Text/Regex/Do/Pcre/Match.hs b/src/Text/Regex/Do/Pcre/Match.hs
deleted file mode 100644
--- a/src/Text/Regex/Do/Pcre/Match.hs
+++ /dev/null
@@ -1,72 +0,0 @@
--- | see "Text.Regex.Base.RegexLike" and "Text.Regex.Do.Pcre.MatchHint"
-module Text.Regex.Do.Pcre.Match
-    (Match(..),
-    R.extract,   -- | 'extract' is reexport from "Text.Regex.Base.RegexLike"
-    makeRegexOpts) where
-
-import qualified Text.Regex.Base.RegexLike as R hiding (makeRegex)
-import Text.Regex.Do.Type.Do
-import Text.Regex.Do.Pcre.Matchf as F
-import Text.Regex.PCRE.Wrap()
-import Text.Regex.Do.Type.Regex_
-
-
-{- | 'match' covers all result types
-
-    compiler looks up the appropriate function depending on the result type
-
-    '=~' is borrowed from "Text.Regex.PCRE.Wrap",
-    is a short version of 'match'
-
-    See also "Text.Regex.Do.Pcre.MatchHint"       -}
-
-class Match a b out where
-    match::Pattern a -> Body b -> out
-    (=~)::a     -- ^ pattern
-        -> b    -- ^ body
-        -> out
-    (=~) p0 b0 = match (Pattern p0) (Body b0)
-
-
--- | match once
-instance Rx_ a b => Match a b [b] where
-    match = once
-{- ^  >>> "^all" =~ "all the time"::[String]
-
-     \["all"\]
-
-     "Text.Regex.Do.Pcre.MatchHint"     -}
-instance Rx_ a b => Match a b Bool where
-    match p0 (Body b0) = R.matchTest (r_ p0) b0
-{- ^ test
-
-    >>> "в" =~ "тихо в лесу"::Bool
-
-    True
-
-    "Text.Regex.Do.Pcre.MatchHint"      -}
-
--- | match all
-instance Rx_ a b => Match a b [[b]] where
-    match = F.all
-{- ^  >>> "well" =~ "all is well that ends well"::[[ByteString]]
-
-     \[["well"\],\["well"\]]
-
-     "Text.Regex.Do.Pcre.MatchHint"    -}
-
--- | match once
-instance Rx_ a b => Match a b [PosLen] where
-    match p0 b0 = maybe [] id $ poslen_ p0 b0
-{- ^ >>> "и" =~ "бывает и хуже"::[PosLen]
-
-     \[(13,2)\]
-
-     /Utf8/
-
-     "Text.Regex.Do.Pcre.MatchHint"     -}
-
--- | match all
-instance Rx_ a b => Match a b [[PosLen]] where
-    match = poslen_
-
diff --git a/src/Text/Regex/Do/Pcre/MatchHint.hs b/src/Text/Regex/Do/Pcre/MatchHint.hs
deleted file mode 100644
--- a/src/Text/Regex/Do/Pcre/MatchHint.hs
+++ /dev/null
@@ -1,82 +0,0 @@
-{- | this module uses
-    <https://cdepillabout.github.io/haskell-type-families-presentation/#/ TypeFamilies>
-
-    this module is similar to "Text.Regex.Do.Pcre.Match". The differences are:
-
-    "Text.Regex.Do.Pcre.Match" is more flexible:
-        accepts 'Pattern' Regex,
-        accepts 'Pattern' and 'Body' of different types
-
-    "Text.Regex.Do.Pcre.Match" needs to infer result type
-
-    in this module the result type is determined by the hint
-    -}
-
-{-# LANGUAGE TypeFamilies #-}
-module Text.Regex.Do.Pcre.MatchHint where
-
-import Text.Regex.Do.Type.Do hiding (Once,All)
-import Text.Regex.PCRE.Wrap()
-import qualified Text.Regex.Do.Pcre.Match as M
-import Text.Regex.Do.Type.MatchHint
-import Data.ByteString
-
-
-{- | picks 'M.Match' instance where 'Pattern' and 'Body' are of the same type
-
-    'Hint' and inferrable 'Pattern' or 'Body' type determine the instance
-
-    handy when working with 'OverloadedStrings', in other cases when compiler needs a hint
-
-    >>> Test ("в"::ByteString) =~ "тихо в лесу"
-
-    True
-
-    >>> Once ("^all"::String) =~ "all the time"
-
-    \["all"\]
-
-    >>> PosLen' ("и"::String) =~ "бывает и хуже"
-
-    \[(13,2)\]      -}
-class (Hint hint, M.Match a a (F hint a)) =>
-    MatchHint hint a where
-    type F hint a
-    match::hint (Pattern a) -> Body a -> F hint a
-    match h0 = M.match $ unhint h0
-
-    (=~)::hint a  -- ^ hint & pattern
-            -> a          -- ^ body
-            -> F hint a   -- ^ type defined by the instance, determined by the hint
-    (=~) h0 = (M.=~) $ unhint h0
-
-
-instance MatchHint Test String where
-    type F Test String = Bool
-
-instance MatchHint PosLen' String where
-    type F PosLen' String = [PosLen]
-
-instance MatchHint PosLen_ String where
-    type F PosLen_ String = [[PosLen]]
-
-instance MatchHint Once String where
-    type F Once String = [String]
-
-instance MatchHint All String where
-    type F All String = [[String]]
-
-instance MatchHint Test ByteString where
-    type F Test ByteString = Bool
-
-instance MatchHint PosLen' ByteString where
-    type F PosLen' ByteString = [PosLen]
-
-instance MatchHint PosLen_ ByteString where
-    type F PosLen_ ByteString = [[PosLen]]
-
-instance MatchHint Once ByteString where
-    type F Once ByteString = [ByteString]
-
-instance MatchHint All ByteString where
-    type F All ByteString = [[ByteString]]
diff --git a/src/Text/Regex/Do/Pcre/Matchf.hs b/src/Text/Regex/Do/Pcre/Matchf.hs
--- a/src/Text/Regex/Do/Pcre/Matchf.hs
+++ b/src/Text/Regex/Do/Pcre/Matchf.hs
@@ -2,26 +2,38 @@
 module Text.Regex.Do.Pcre.Matchf where
 
 import Text.Regex.Do.Type.Do
-import Text.Regex.Do.Type.Reexport
-import qualified Text.Regex.Do.Pcre.Result as R
-import qualified Text.Regex.Base.RegexLike as R hiding (makeRegex)
-import Text.Regex.Do.Type.Regex_
+import Text.Regex.Do.Type.Reexport as R
+import Text.Regex.Do.Result as R
+import Text.Regex.Base.RegexLike as R
+import Text.Regex.Do.Type.MatchHint
 
+type R_ b = R.RegexLike R.Regex b
 
-class (Rx_ a b, Functor f) => Matchf f a b where
-   marray_::Pattern a -> Body b -> f MatchArray
-   poslen_::Pattern a -> Body b -> f [PosLen]
-   poslen_ r0 b0 = R.poslen $ marray_ r0 b0
 
-instance Rx_ a b => Matchf Maybe a b where
-   marray_ p0 (Body b0) = R.matchOnce (r_ p0) b0
+class Matchf hint b where
+    type H hint
+    type P hint
+    marray_::R_ b => hint (Pattern R.Regex) -> Body b -> H hint
+    poslen_::R_ b => hint (Pattern R.Regex) -> Body b -> P hint
 
-instance Rx_ a b => Matchf [] a b where
-   marray_ p0 (Body b0) = R.matchAll (r_ p0) b0
+instance Matchf Once b where
+    type H Once = Maybe MatchArray
+    type P Once = Maybe [PosLen]
+    marray_ (Once (Pattern p0)) (Body b0) = R.matchOnce p0 b0
+    poslen_ r0 b0 = R.poslen $ marray_ r0 b0
 
+instance Matchf All b where
+    type H All = [MatchArray]
+    type P All = [[PosLen]]
+    marray_ (All (Pattern p0)) (Body b0) = R.matchAll p0 b0
+    poslen_ r0 b0 = R.poslen $ marray_ r0 b0
 
-once::Rx_ a b => Pattern a -> Body b -> [b]      -- ^ matched content
-once p0 b0 = maybe [] id $ R.allMatches b0 $ marray_ p0 b0
 
-all::Rx_ a b => Pattern a -> Body b -> [[b]]       -- ^ matched content
-all p0 b0 = R.allMatches b0 $ marray_ p0 b0
+once::(R_ b, R.Extract b) =>
+    Pattern R.Regex -> Body b -> [b]      -- ^ matched content
+once p0 b0 = maybe [] id $ R.allMatches b0 $ marray_ (Once p0) b0
+
+
+all::(R_ b, R.Extract b) =>
+    Pattern R.Regex -> Body b -> [[b]]       -- ^ matched content
+all p0 b0 = R.allMatches b0 $ marray_ (All p0) b0
diff --git a/src/Text/Regex/Do/Pcre/Replace.hs b/src/Text/Regex/Do/Pcre/Replace.hs
deleted file mode 100644
--- a/src/Text/Regex/Do/Pcre/Replace.hs
+++ /dev/null
@@ -1,127 +0,0 @@
-module Text.Regex.Do.Pcre.Replace
-    (Replace(..))  where
-
-import Text.Regex.Base.RegexLike as R
-import Prelude as P
-import Data.ByteString as B
-import qualified Text.Regex.Do.Pcre.Option as O
-import Text.Regex.Do.Type.Do
-import Text.Regex.Do.Type.Reexport
-import Text.Regex.Do.Pcre.Matchf
-import qualified Text.Regex.Do.Pcre.ReplaceOpen as O
-import Text.Regex.Do.Convert
-import Text.Regex.Do.Type.Regex_
-import Text.Regex.Do.Type.Extract
-import Text.Regex.Do.Type.MatchHint
-
-
-
-type Ro_ rx = (Regex_ rx, Opt_ rx)
-
-rx'::Regex_ rx => Pattern rx -> [O.Comp] -> Pattern Regex
-rx' p0 opt0 = Pattern $ ropt_ p0 opt0 []
-
-
-{- | == dynamic group replace
-   custom replacer fn returns replacement value. See 'O.defaultReplacer'
-
-   >>> replacer::GroupReplacer String
-       replacer = defaultReplacer 1 tweak1
-             where tweak1 str1 = case str1 of
-                                   "101" -> "[сто один]"
-                                   "3" -> "[three]"
-                                   otherwise -> trace str1 "?"
-
-    'Once' vs 'All' options
-
-    >>> replace (Once[]) (Pattern "\\w=(\\d{1,3})") replacer $ Body "a=101 b=3 12"
-
-        "a=[сто один] b=3 12"
-
-    >>> replace (All[]) (Pattern "\\w=(\\d{1,3})") replacer $ Body "a=101 b=3 12"
-
-        "a=[сто один] b=[three] 12"
-
-
-    == static replace for simple (no group) needle
-
-    for no-regex 'ByteString' replacement see "Text.Regex.Do.Split"
-
-    >>> replace (Once[Utf8]) (Pattern "менее") (Replacement  "более") $ Body "менее менее"
-
-    "более менее"
-
-    >>> replace (Once[]) (Pattern "^a\\s") (Replacement "A") $ Body "a bc хол.гор."
-
-    "Abc хол.гор."      -}
-
-class Replace hint rx r a where
-    replace::hint [O.Comp] -> Pattern rx -> r a -> Body a -> a
-
-
-instance Regex_ rx => Replace Once rx Replacement String where
-    replace opt0@(Once opt1) p0 r0 b0 =
-        let ma1 = marray_ p1 b1::Maybe MatchArray
-            b1 = toByteString <$> b0
-            r1 = toByteString <$> r0
-            isUtf1 = O.Utf8 `P.elem` opt1
-            bs1 = O.replace ma1 r1 b1
-            p1 = rx' p0 opt1
-        in if isUtf1 then toString bs1
-            else vanilla_once p1 r0 b0
-
-
-instance Regex_ rx => Replace All rx Replacement String where
-    replace opt0@(All opt1) p0 r0 b0 =
-        let ma2 = marray_ p0 b1::[MatchArray]
-            b1 = toByteString <$> b0
-            r1 = toByteString <$> r0
-            isUtf1 = O.Utf8 `P.elem` opt1
-            bs1 = O.replace ma2 r1 b1
-            p1 = rx' p0 opt1
-        in if isUtf1 then toString bs1
-            else vanilla_all p1 r0 b0
-
-
-instance Regex_ rx => Replace Once rx Replacement ByteString where
-    replace opt0@(Once opt1) p0 = vanilla_once $ rx' p0 opt1
-
-instance Regex_ rx => Replace All rx Replacement ByteString where
-    replace opt0@(All opt1) p0 = vanilla_all $ rx' p0 opt1
-
-instance Regex_ rx => Replace Once rx GroupReplacer ByteString where
-    replace opt0@(Once opt1) p0 = vanilla_once $ rx' p0 opt1
-
-instance Regex_ rx => Replace All rx GroupReplacer ByteString where
-    replace opt0@(All opt1) p0 = vanilla_all $ rx' p0 opt1
-
-instance Regex_ rx => Replace Once rx GroupReplacer String where
-    replace opt0@(Once opt1) p0 = vanilla_once $ rx' p0 opt1
-
-instance Regex_ rx => Replace All rx GroupReplacer String where
-    replace opt0@(All opt1) p0 = vanilla_all $ rx' p0 opt1
-
-
-type Vanilla_ f r a = (O.ReplaceOpen f r, Extract' a, RegexLike Regex a)
-type Vanilla_once r a = Vanilla_ Maybe r a
-type Vanilla_all r a = Vanilla_ [] r a
-
-
-vanilla_once::Vanilla_once r a =>
-        Pattern Regex ->
-        r a ->
-        Body a ->
-            a
-vanilla_once p0 r0 b0 =
-   let ma1 = marray_ p0 b0::Maybe MatchArray
-   in O.replace ma1 r0 b0
-
-
-vanilla_all::Vanilla_all r a =>
-        Pattern Regex ->
-        r a ->
-        Body a ->
-            a
-vanilla_all p0 r0 b0 =
-   let ma2 = marray_ p0 b0:: [MatchArray]
-   in O.replace ma2 r0 b0
diff --git a/src/Text/Regex/Do/Pcre/ReplaceOpen.hs b/src/Text/Regex/Do/Pcre/ReplaceOpen.hs
deleted file mode 100644
--- a/src/Text/Regex/Do/Pcre/ReplaceOpen.hs
+++ /dev/null
@@ -1,144 +0,0 @@
-{- | extensible and reusable replacement functions
-
-    Run replacement with your preferred content types e.g. "Data.Text",
-    from search results with non-PCRE regex or non-regex libs
-
-    open an issue or a PR on <https://github.com/ciez/regex-do git> to request a new 'Extract'' instance
-
-    "Data.Text" instance already works  -}
-
-module Text.Regex.Do.Pcre.ReplaceOpen
-    (ReplaceOpen(..),
-    defaultReplacer,
-    getGroup,
-    replaceMatch
-    )
-    where
-
-import Text.Regex.Base.RegexLike as R
-import Data.Array as A
-import Prelude as P
-import Text.Regex.Do.Type.Do
-import Text.Regex.Do.Pcre.Result as R
-import Text.Regex.Do.Convert
-import Text.Regex.Do.Type.Extract
-
-
-{- | 'Replacement':
-
-    >>> replace (Just [(4,3)::PosLen]) (Replacement "4567") (Body "abc 123 def"::Body Text)
-
-    "abc 4567 def"
-
-
-    'GroupReplacer' :
-
-    >>> replacer::GroupReplacer Text
-        replacer = defaultReplacer 1 tweak1        --  1: first match in group
-              where tweak1 str1 = case str1 of
-                                    "123" -> "[1-2-3]"
-                                    otherwise -> traceShow str1 "?"
-
-    >>> replace (Just ([(4,3),(8,2)]::[PosLen])) replacer (Body "abc 123 def"::Body Text)
-
-        "abc [1-2-3] def"     -}
-
-class ReplaceOpen f r where
-   replace::(Extract' a, ToArray arr) =>
-        f arr -> r a -> Body a -> a
-
-
-instance ReplaceOpen Maybe Replacement where
-   replace Nothing (Replacement repl0) (Body b0) = b0
-   replace (Just ma0) (Replacement repl0) (Body b0) = firstGroup lpl1 (repl0, b0)
-        where lpl1 = A.elems $ toArray ma0
-
-
-instance ReplaceOpen [] Replacement where
-   replace [] _ (Body b0) = b0
-   replace ma0 (Replacement repl0) (Body b0) =
-      let lpl1 = R.poslen $ toArray <$> ma0::[[PosLen]]
-          foldFn1 lpl1 acc1 = firstGroup lpl1 (repl0,acc1)
-      in P.foldr foldFn1 b0 lpl1
-
-
-instance ReplaceOpen Maybe GroupReplacer where
-   replace Nothing _ (Body b0) = b0
-   replace (Just ma0) (GroupReplacer repl0) (Body b0) =
-            let a1 = ReplaceAcc {
-                                  acc = b0,
-                                  pos_adj = 0
-                                }
-            in acc $ repl0 (toArray ma0) a1
-
-
-instance ReplaceOpen [] GroupReplacer where
-   replace [] _ (Body b0) = b0
-   replace ma0 (GroupReplacer repl0) (Body b0) =
-        let acc1 = ReplaceAcc { acc = b0, pos_adj = 0 }
-        in acc $ P.foldl (flip repl0) acc1 $ toArray <$> ma0
-
-
-firstGroup::Extract' a =>
-    [PosLen] -> (a,a) -> a
-firstGroup (pl0:_) r1@(new0,a0) = acc $ replaceMatch pl0 (new0, acc1)
-    where acc1 = ReplaceAcc {
-                    acc = a0,
-                    pos_adj = 0
-                    }
-
-
-
---  dynamic
-{- | Replaces specified (by idx) group match with tweaked value.
-    Works for one common simple use case
-
-    'GroupReplacer' can be used with complicated regex
-
-    another custom dynamic replacer could e.g.
-    inspect all group matches before looking up a replacement.     -}
-defaultReplacer::Extract' a =>
-        Int         -- ^ group idx
-        -> (a -> a) -- ^ (group match -> replacement) tweak
-            -> GroupReplacer a
-defaultReplacer idx0 tweak0 = GroupReplacer fn1
-    where fn1 (ma0::MatchArray) acc0 = maybe acc0 fn1 mval1
-                where pl1 = ma0 A.! idx0 :: (R.MatchOffset, R.MatchLength)
-                      mval1 = getGroup acc0 ma0 idx0
-                      fn1 str1 = replaceMatch pl1 (str2, acc0)
-                                 where str2 = tweak0 str1
-
-
-{- | get group content safely
-
-    see 'defaultReplacer' source for use example
-    -}
-getGroup::R.Extract a =>
-    ReplaceAcc a -> MatchArray -> Int -> Maybe a
-getGroup acc0 ma0 idx0 = if idx0 >= P.length ma0 then Nothing     --  safety catch
-    else Just val1
-    where pl1 = ma0 A.! idx0 :: (R.MatchOffset, R.MatchLength)
-          pl2 = adjustPoslen pl1 acc0
-          val1 = extract pl2 $ acc acc0
-
-
-{- | call from your custom 'GroupReplacer' passed to 'replaceGroup'
-
-     see 'defaultReplacer' source for use example     -}
-replaceMatch::Extract' a =>
-        PosLen      -- ^ replaceable, unadjusted
-        -> (a, ReplaceAcc a)  -- ^ (new val, acc passed to 'GroupReplacer')
-        -> ReplaceAcc a    -- ^ new acc
-replaceMatch pl0@(_,l0) (new0, acc0) = ReplaceAcc {
-                    acc = acc1,
-                    pos_adj = pos_adj acc0 + l1 - l0
-                    }
-     where  pl1 = adjustPoslen pl0 acc0
-            prefix1 = prefix pl1 $ acc acc0
-            suffix1 = suffix pl1 $ acc acc0
-            acc1 = concat' [prefix1, new0, suffix1]
-            l1 = len' new0
-
-
-adjustPoslen::PosLen -> ReplaceAcc a -> PosLen
-adjustPoslen (p0,l0) acc0  = (p0 + pos_adj acc0, l0)
diff --git a/src/Text/Regex/Do/Pcre/Result.hs b/src/Text/Regex/Do/Pcre/Result.hs
deleted file mode 100644
--- a/src/Text/Regex/Do/Pcre/Result.hs
+++ /dev/null
@@ -1,22 +0,0 @@
-module Text.Regex.Do.Pcre.Result where
-
-import qualified Data.Array as A(elems)
-import Text.Regex.Base.RegexLike as R
-import Text.Regex.Do.Type.Do
-
--- | match offset, length
-poslen::Functor f =>
-    f MatchArray -> f [PosLen]
-poslen = (A.elems <$>)
-
-
--- | all groups
-allMatches::(Functor f, R.Extract b) =>
-    Body b -> f MatchArray -> f [b]
-allMatches hay0 results0 = groupMatch hay0 <$> results0
-
-
--- | matches for one group
-groupMatch::R.Extract b =>
-    Body b -> MatchArray -> [b]
-groupMatch (Body b0) a0 = [R.extract tuple1 b0 |  tuple1 <- A.elems a0]
diff --git a/src/Text/Regex/Do/Pcre/Utf8/Match.hs b/src/Text/Regex/Do/Pcre/Utf8/Match.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Regex/Do/Pcre/Utf8/Match.hs
@@ -0,0 +1,80 @@
+{- | see "Text.Regex.Base.RegexLike" and "Text.Regex.Do.Pcre.Utf8.MatchHint"
+
+    similar to "Text.Regex.Do.Pcre.Ascii.Match"
+
+    'Pattern' & 'Body' are wrapped in 'Utf8_' encoding tag.
+    This tag adds clarity, prevents calling Ascii functions by mistake.
+
+    __'toByteString''__ converts String to 'Utf8_' 'ByteString'     -}
+module Text.Regex.Do.Pcre.Utf8.Match
+    (Match(..),
+    (=~),
+    R.extract   -- | 'extract' is reexport from "Text.Regex.Base.RegexLike"
+    ) where
+
+import Text.Regex.Do.Type.Reexport as R
+import qualified Text.Regex.Base.RegexLike as R hiding (makeRegex)
+import Text.Regex.Do.Type.Do
+import Text.Regex.Do.Pcre.Matchf as F
+import Text.Regex.PCRE.Wrap()
+import Text.Regex.Do.Type.Regex as T
+import Text.Regex.Do.Type.MatchHint
+import Text.Regex.Do.Pcre.Option
+import Text.Regex.Do.Convert
+import Data.ByteString
+
+
+
+class Match enc a b out where
+    match::Pattern (enc a) -> Body (enc b) -> out
+
+(=~)::Match Utf8_ a b out =>
+    a     -- ^ pattern
+    -> b    -- ^ body
+    -> out
+(=~) p0 b0 = match (Pattern $ Utf8_ p0) (Body $ Utf8_ b0)
+
+
+-- | match once
+instance Rx_ a b => Match Utf8_ a b [b] where
+    match p0 b0 = once (mr_ p0) $ val <$> b0
+
+{- ^ >>> let rx1 = makeRegexOpt' (Pattern $ toByteString' "左") [] []      --  add options as needed
+         rx2 = Utf8_ <$> rx1
+         m1 = U.match rx2 (Body $ toByteString' "100メートル左折後、左")::[ByteString]
+      m1 `shouldBe` [toByteString "左"]        -}
+
+
+instance Rx_ a b => Match Utf8_ a b Bool where
+    match p0 (Body b0) = R.matchTest (makeRegexOpt p0 [Utf8] []) $ val b0
+{- ^ test. Note that a and b may be different types e.g. 'ByteString' and 'String'
+
+    >>>  toByteString "в" =~ ("тихо в лесу"::String)::Bool
+
+    True        -}
+
+-- | match all
+instance Rx_ a b => Match Utf8_ a b [[b]] where
+    match p0 b0 = F.all (mr_ p0) $ val <$> b0
+{- ^  >>> ("well"::String) =~ ("all is well that ends well"::String)::[[String]]
+
+     \[["well"\],\["well"\]]        -}
+
+-- | match once
+instance Rx_ a b => Match Utf8_ a b [PosLen] where
+    match p0 b0 = maybe [] id $ poslen_ (Once $ mr_ p0) $ val <$> b0
+{- ^ >>> ("и"::String) =~ ("бывает и хуже"::String)::[PosLen]
+
+     \[(13,2)\]     -}
+
+-- | match all
+instance Rx_ a b => Match Utf8_ a b [[PosLen]] where
+    match p0 b0 = poslen_ (All $ mr_ p0) $ val <$> b0
+
+
+mr_::T.Regex a => Pattern a -> Pattern R.Regex
+mr_ p0 = makeRegexOpt' p0 [Utf8] []
+
+
+dum_::String -> Utf8_ ByteString
+dum_ = toByteString'
diff --git a/src/Text/Regex/Do/Pcre/Utf8/MatchHint.hs b/src/Text/Regex/Do/Pcre/Utf8/MatchHint.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Regex/Do/Pcre/Utf8/MatchHint.hs
@@ -0,0 +1,75 @@
+-- | see "Text.Regex.Do.Pcre.Ascii.MatchHint" about MatchHint vs Match
+
+
+module Text.Regex.Do.Pcre.Utf8.MatchHint
+    (MatchHint(..),
+    (=~)) where
+
+import Text.Regex.Do.Type.Do hiding (Once,All)
+import Text.Regex.PCRE.Wrap()
+import qualified Text.Regex.Do.Pcre.Utf8.Match as M
+import Text.Regex.Do.Type.MatchHint
+import Data.ByteString
+
+
+{- | picks 'M.Match' instance where 'Pattern' and 'Body' are of the same type
+
+    'Hint' and inferrable 'Pattern' or 'Body' type determine the instance
+
+    handy when working with 'OverloadedStrings', in other cases when compiler needs a hint  -}
+class (Hint hint, M.Match enc a a (F hint a)) =>
+    MatchHint hint enc a where
+    type F hint a
+    match::hint (Pattern (enc a)) -> Body (enc a) -> F hint a
+    match h0 = M.match $ unhint h0
+
+
+(=~)::MatchHint hint Utf8_ a =>
+    hint a              -- ^ hint pattern
+        -> a            -- ^ body
+        -> F hint a     -- ^ type defined by the instance, determined by the hint
+(=~) h0 = (M.=~) $ unhint h0
+
+
+instance MatchHint Test Utf8_ String where
+    type F Test String = Bool
+
+
+instance MatchHint PosLen' Utf8_ String where
+    type F PosLen' String = [PosLen]
+
+{- ^ >>> PosLen' ("и"::String) =~ "бывает и хуже"
+
+    \[(13,2)\]      -}
+
+instance MatchHint PosLen_ Utf8_ String where
+    type F PosLen_ String = [[PosLen]]
+
+instance MatchHint Once Utf8_ String where
+    type F Once String = [String]
+
+{- ^ >>> Once ("^all"::String) =~ "all the time"
+
+    \["all"\]       -}
+
+instance MatchHint All Utf8_ String where
+    type F All String = [[String]]
+
+instance MatchHint Test Utf8_ ByteString where
+    type F Test ByteString = Bool
+
+{- ^ >>> Test (toByteString "в") =~ toByteString "тихо в лесу"
+
+    True    -}
+
+instance MatchHint PosLen' Utf8_ ByteString where
+    type F PosLen' ByteString = [PosLen]
+
+instance MatchHint PosLen_ Utf8_ ByteString where
+    type F PosLen_ ByteString = [[PosLen]]
+
+instance MatchHint Once Utf8_ ByteString where
+    type F Once ByteString = [ByteString]
+
+instance MatchHint All Utf8_ ByteString where
+    type F All ByteString = [[ByteString]]
diff --git a/src/Text/Regex/Do/Pcre/Utf8/Replace.hs b/src/Text/Regex/Do/Pcre/Utf8/Replace.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Regex/Do/Pcre/Utf8/Replace.hs
@@ -0,0 +1,83 @@
+{- | see also "Text.Regex.Do.Pcre.Ascii.Replace"
+
+    'Pattern' & 'Body' are wrapped in 'Utf8_' encoding tag.
+    This tag adds clarity, prevents calling Ascii functions by mistake.
+
+    __'toByteString''__ converts String to 'Utf8_' 'ByteString'     -}
+
+module Text.Regex.Do.Pcre.Utf8.Replace
+    (Replace(..))  where
+
+import Prelude as P
+import Text.Regex.Do.Type.Do
+import Text.Regex.Do.Pcre.Matchf
+import qualified Text.Regex.Do.ReplaceOpen as O
+import Text.Regex.Do.Type.Regex as T
+import Text.Regex.Do.Type.MatchHint
+import Text.Regex.Do.Convert
+import Data.ByteString
+
+
+class Replace all enc a repl where
+    replace::all (Pattern (enc a)) -> repl (enc a) -> Body (enc a) -> a
+
+
+instance Replace Once Utf8_ String Replacement where
+    replace = replace_str marray_
+
+instance Replace All Utf8_ String Replacement where
+    replace = replace_str marray_
+
+replace_str f0 p0 r0 b0 =
+   let ma1 = f0 p1 b1
+       b1 = toByteString . val <$> b0
+       r1 = toByteString <$> (val <$> r0)
+       p1 = T.makeRegex' . (toByteString' . val <$>) <$> p0
+   in toString $ O.replace ma1 r1 b1
+
+
+instance Replace Once Utf8_ ByteString Replacement where
+    replace = replace_bs marray_
+
+instance Replace All Utf8_ ByteString Replacement where
+    replace = replace_bs marray_
+
+replace_bs f0 p0 r0 b0 =
+   let ma1 = f0 p1 b1
+       b1 = val <$> b0
+       p1 = T.makeRegex' . (Utf8_ . val <$>) <$> p0
+   in O.replace ma1 (val <$> r0) b1
+
+
+
+instance Replace Once Utf8_ ByteString GroupReplacer where
+    replace = replace_bs' marray_
+
+instance Replace All Utf8_ ByteString GroupReplacer where
+    replace = replace_bs' marray_
+
+{- ^ >>> replacer::GroupReplacer (Utf8_ ByteString)
+         replacer = defaultReplacer 1 tweak1
+          where tweak1 bs1 = toByteString' $
+                                if bs1 == toByteString' "左" then
+                                      "ー右ー"
+                                       else "?"
+
+
+     >>> runFn1 `shouldBe` toByteString "100メートルー右ー折後、左"
+            where runFn1 =
+                     let rx1 = Pattern $ toByteString' "(?<=ル)(左)"
+                         body1 = Body $ toByteString' "100メートル左折後、左"
+                     in replace (All rx1) replacer body1        -}
+
+
+replace_bs' f0 p0 r0 b0 =
+   let ma1 = f0 p1 b1
+       b1 = val <$> b0
+       p1 = T.makeRegex' . (Utf8_ . val <$>) <$> p0
+   in O.replace ma1 (val' r0) b1
+
+
+{- ^ to tweak regex with 'Comp' or 'Exec', see "Text.Regex.Do.Type.Regex"
+
+    note 'Once_Utf8' and 'All_Utf8' hints   -}
diff --git a/src/Text/Regex/Do/ReplaceOpen.hs b/src/Text/Regex/Do/ReplaceOpen.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Regex/Do/ReplaceOpen.hs
@@ -0,0 +1,143 @@
+{- | extensible and reusable replacement functions
+
+    Run replacement with your preferred content types e.g. "Data.Text",
+    from search results with non-PCRE regex or non-regex libs
+
+    open an issue or a PR on <https://github.com/ciez/regex-do git> to request a new 'Extract'' instance
+
+    "Data.Text" instance already works  -}
+
+module Text.Regex.Do.ReplaceOpen
+    (ReplaceOpen(..),
+    defaultReplacer,
+    getGroup,
+    replaceMatch
+    )
+    where
+
+import Text.Regex.Base.RegexLike as R
+import Data.Array as A
+import Prelude as P
+import Text.Regex.Do.Type.Do
+import Text.Regex.Do.Result as R
+import Text.Regex.Do.Convert
+import Text.Regex.Do.Type.Extract
+
+
+{- | 'Replacement':
+
+    >>> replace (Just [(4,3)::PosLen]) (Replacement "4567") (Body "abc 123 def"::Body Text)
+
+    "abc 4567 def"
+
+
+    'GroupReplacer' :
+
+    >>> replacer::GroupReplacer Text
+        replacer = defaultReplacer 1 tweak1        --  1: first match in group
+              where tweak1 str1 = case str1 of
+                                    "123" -> "[1-2-3]"
+                                    otherwise -> traceShow str1 "?"
+
+    >>> replace (Just ([(4,3),(8,2)]::[PosLen])) replacer (Body "abc 123 def"::Body Text)
+
+        "abc [1-2-3] def"     -}
+
+class ReplaceOpen f r where
+   replace::(Extract' a, ToArray arr) =>
+        f arr -> r a -> Body a -> a
+
+
+instance ReplaceOpen Maybe Replacement where
+   replace Nothing (Replacement repl0) (Body b0) = b0
+   replace (Just ma0) (Replacement repl0) (Body b0) = firstGroup lpl1 (repl0, b0)
+        where lpl1 = A.elems $ toArray ma0
+
+
+instance ReplaceOpen [] Replacement where
+   replace [] _ (Body b0) = b0
+   replace ma0 (Replacement repl0) (Body b0) =
+      let lpl1 = R.poslen $ toArray <$> ma0::[[PosLen]]
+          foldFn1 lpl1 acc1 = firstGroup lpl1 (repl0,acc1)
+      in P.foldr foldFn1 b0 lpl1
+
+
+instance ReplaceOpen Maybe GroupReplacer where
+   replace Nothing _ (Body b0) = b0
+   replace (Just ma0) (GroupReplacer repl0) (Body b0) =
+            let a1 = ReplaceAcc {
+                                  acc = b0,
+                                  pos_adj = 0
+                                }
+            in acc $ repl0 (toArray ma0) a1
+
+
+instance ReplaceOpen [] GroupReplacer where
+   replace [] _ (Body b0) = b0
+   replace ma0 (GroupReplacer repl0) (Body b0) =
+        let acc1 = ReplaceAcc { acc = b0, pos_adj = 0 }
+        in acc $ P.foldl (flip repl0) acc1 $ toArray <$> ma0
+
+
+firstGroup::Extract' a =>
+    [PosLen] -> (a,a) -> a
+firstGroup (pl0:_) r1@(new0,a0) = acc $ replaceMatch pl0 (new0, acc1)
+    where acc1 = ReplaceAcc {
+                    acc = a0,
+                    pos_adj = 0
+                    }
+
+
+--  dynamic
+{- | Replaces specified (by idx) group match with tweaked value.
+    Works for one common simple use case
+
+    'GroupReplacer' can be used with complicated regex
+
+    another custom dynamic replacer could e.g.
+    inspect all group matches before looking up a replacement.     -}
+defaultReplacer::Extract' a =>
+        Int         -- ^ group idx
+        -> (a -> a) -- ^ (group match -> replacement) tweak
+            -> GroupReplacer a
+defaultReplacer idx0 tweak0 = GroupReplacer fn1
+    where fn1 (ma0::MatchArray) acc0 = maybe acc0 fn1 mval1
+                where pl1 = ma0 A.! idx0 :: (R.MatchOffset, R.MatchLength)
+                      mval1 = getGroup acc0 ma0 idx0
+                      fn1 str1 = replaceMatch pl1 (str2, acc0)
+                                 where str2 = tweak0 str1
+
+
+{- | get group content safely
+
+    see 'defaultReplacer' source for use example
+    -}
+getGroup::R.Extract a =>
+    ReplaceAcc a -> MatchArray -> Int -> Maybe a
+getGroup acc0 ma0 idx0 = if idx0 >= P.length ma0 then Nothing     --  safety catch
+    else Just val1
+    where pl1 = ma0 A.! idx0 :: (R.MatchOffset, R.MatchLength)
+          pl2 = adjustPoslen pl1 acc0
+          val1 = extract pl2 $ acc acc0
+
+
+{- | call from your custom 'GroupReplacer' passed to 'replaceGroup'
+
+     see 'defaultReplacer' source for use example     -}
+replaceMatch::Extract' a =>
+        PosLen      -- ^ replaceable, unadjusted
+        -> (a, ReplaceAcc a)  -- ^ (new val, acc passed to 'GroupReplacer')
+        -> ReplaceAcc a    -- ^ new acc
+replaceMatch pl0@(_,l0) (new0, acc0) = ReplaceAcc {
+                    acc = acc1,
+                    pos_adj = pos_adj acc0 + l1 - l0
+                    }
+     where  pl1 = adjustPoslen pl0 acc0
+            prefix1 = prefix pl1 $ acc acc0
+            suffix1 = suffix pl1 $ acc acc0
+            acc1 = concat' [prefix1, new0, suffix1]
+            l1 = len' new0
+
+
+adjustPoslen::PosLen -> ReplaceAcc a -> PosLen
+adjustPoslen (p0,l0) acc0  = (p0 + pos_adj acc0, l0)
diff --git a/src/Text/Regex/Do/Result.hs b/src/Text/Regex/Do/Result.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Regex/Do/Result.hs
@@ -0,0 +1,22 @@
+module Text.Regex.Do.Result where
+
+import qualified Data.Array as A(elems)
+import Text.Regex.Base.RegexLike as R
+import Text.Regex.Do.Type.Do
+
+-- | match offset, length
+poslen::Functor f =>
+    f MatchArray -> f [PosLen]
+poslen = (A.elems <$>)
+
+
+-- | all groups
+allMatches::(Functor f, R.Extract b) =>
+    Body b -> f MatchArray -> f [b]
+allMatches hay0 results0 = groupMatch hay0 <$> results0
+
+
+-- | matches for one group
+groupMatch::R.Extract b =>
+    Body b -> MatchArray -> [b]
+groupMatch (Body b0) a0 = [R.extract tuple1 b0 |  tuple1 <- A.elems a0]
diff --git a/src/Text/Regex/Do/Trim.hs b/src/Text/Regex/Do/Trim.hs
--- a/src/Text/Regex/Do/Trim.hs
+++ b/src/Text/Regex/Do/Trim.hs
@@ -4,8 +4,10 @@
 import Data.Char(isSpace)
 import qualified Data.ByteString as B
 import Text.Regex.Do.Convert
-import Text.Regex.Do.Pcre.Replace
+import Text.Regex.Do.Pcre.Ascii.Replace
 import Text.Regex.Do.Type.MatchHint
+import Text.Regex.Do.Type.Regex
+import Text.Regex.Do.Pcre.Option
 
 
 {- | removes leading and trailing spaces and tabs   -}
@@ -15,10 +17,12 @@
 
 
 instance Trim B.ByteString where
-    trim bs1 = replace (All []) rx1 repl1 $ Body bs1
+    trim bs1 = replace (All rx2) repl1 $ Body bs1
        where repl1 = Replacement B.empty
-             rx1 = rxFn "(^[\\s\\t]+)|([\\s\\t]+$)"
-             rxFn = Pattern . toByteString
+             rx1 = "(^[\\s\\t]+)|([\\s\\t]+$)"
+             rx2 = let p1 = Pattern $ toByteString rx1
+                        in makeRegexOpt' p1 [Blank] []
+
 
 instance  Trim String where
     trim = f . f
diff --git a/src/Text/Regex/Do/Type/Do.hs b/src/Text/Regex/Do/Type/Do.hs
--- a/src/Text/Regex/Do/Type/Do.hs
+++ b/src/Text/Regex/Do/Type/Do.hs
@@ -6,20 +6,66 @@
 -- | see "Text.Regex.Do.Pcre.ReplaceOpen" 'defaultReplacer' for example implementation
 newtype GroupReplacer b = GroupReplacer (MatchArray -> ReplaceAcc b -> ReplaceAcc b) -- MatchArray -> acc -> acc
 
-
 data ReplaceAcc b = ReplaceAcc {
     acc::b,   -- ^ content with some replacements made
     pos_adj::Int    {- ^ position adjustment: group replacement length may differ from replaced text length -}
     }
 
+instance Functor ReplaceAcc where
+    fmap fn0 r0 = r0 { acc = fn0 $ acc r0 }
 
+
+
 -- | Needle
 data Pattern a = Pattern a  deriving (Functor)          -- Bs, String, RegexPcre
+instance Applicative Pattern where
+    pure p0 = Pattern p0
+    (<*>) (Pattern f0) (Pattern a0) = Pattern $ f0 a0
 
+
 -- | Haystack
 data Body b = Body b deriving (Functor)                -- Bs, String
+instance Applicative Body where
+    pure p0 = Body p0
+    (<*>) (Body f0) (Body a0) = Body $ f0 a0
 
+
 data Replacement r = Replacement r deriving (Functor)     --    Bs, String
+instance Applicative Replacement where
+    pure p0 = Replacement p0
+    (<*>) (Replacement f0) (Replacement a0) = Replacement $ f0 a0
 
 -- | Offset, Length
 type PosLen = (MatchOffset, MatchLength)
+
+
+
+newtype Utf8_ a = Utf8_ a       -- ^ values
+        deriving (Functor,Eq,Ord)
+
+instance Applicative Utf8_ where
+    pure p0 = Utf8_ p0
+    (<*>) (Utf8_ f0) (Utf8_ a0) = Utf8_ $ f0 a0
+
+
+-- ^ does not do any codec. Plain wrap / unwrap newtype
+class Enc enc where
+    val::enc a -> a
+    enc::a -> enc a
+
+-- ^ does not do any codec. Plain wrap / unwrap newtype
+class Enc' f enc where
+    val'::f (enc a) -> f a
+    enc'::f a -> f (enc a)
+
+
+instance Enc Utf8_ where
+    val (Utf8_ v0) = v0
+    enc = Utf8_
+
+
+instance Enc enc => Enc' GroupReplacer enc where
+    val' (GroupReplacer fn0) = GroupReplacer $
+        \ma1 acc1 -> val <$> (fn0 ma1 $ enc <$> acc1)
+    enc' (GroupReplacer fn0) = GroupReplacer $
+        \ma1 acc1 -> enc <$> (fn0 ma1 $ val <$> acc1)
diff --git a/src/Text/Regex/Do/Type/Extract.hs b/src/Text/Regex/Do/Type/Extract.hs
--- a/src/Text/Regex/Do/Type/Extract.hs
+++ b/src/Text/Regex/Do/Type/Extract.hs
@@ -1,9 +1,11 @@
 module Text.Regex.Do.Type.Extract where
 
-import Text.Regex.Base.RegexLike as R
+import Text.Regex.Base.RegexLike as R hiding (empty)
+import qualified Text.Regex.Base.RegexLike as R (empty)
 import Prelude as P
 import Data.ByteString as B
-import Data.Text as T
+import Data.Text as T hiding (empty)
+import qualified Data.Text as T (empty)
 import Text.Regex.Do.Type.Do
 
 
@@ -23,6 +25,17 @@
 instance Extract' B.ByteString where
    concat' = B.concat
    len' = B.length
+
+
+instance Extract (Utf8_ B.ByteString) where
+    before i0 = (before i0 <$>)
+    after i0 = (after i0 <$>)
+    empty = Utf8_ R.empty
+
+
+instance Extract' (Utf8_ B.ByteString) where
+   concat' = Utf8_ . B.concat . (val <$>)
+   len' = B.length . val
 
 
 instance Extract Text where
diff --git a/src/Text/Regex/Do/Type/MatchHint.hs b/src/Text/Regex/Do/Type/MatchHint.hs
--- a/src/Text/Regex/Do/Type/MatchHint.hs
+++ b/src/Text/Regex/Do/Type/MatchHint.hs
@@ -2,17 +2,46 @@
 
 newtype Test a = Test a     -- ^ test: does body match pattern?
 newtype Once a = Once a     -- ^ values
-newtype All a = All a       -- ^ values
+        deriving (Functor)
+
+newtype All a = All a        -- ^ values
+        deriving (Functor)
+
 newtype PosLen' a = PosLen' a   -- ^ once
 newtype PosLen_ a = PosLen_ a   -- ^ all
 
 
 class Hint hint where
     unhint::hint a -> a
+    hint::a -> hint a
 
 
-instance Hint Test where unhint (Test a0) = a0
-instance Hint Once where unhint (Once a0) = a0
-instance Hint All where unhint (All a0) = a0
-instance Hint PosLen' where unhint (PosLen' a0) = a0
-instance Hint PosLen_ where unhint (PosLen_ a0) = a0
+instance Hint Test where
+    unhint (Test a0) = a0
+    hint = Test
+
+instance Hint Once where
+    unhint (Once a0) = a0
+    hint = Once
+
+instance Hint All where
+    unhint (All a0) = a0
+    hint = All
+
+instance Hint PosLen' where
+    unhint (PosLen' a0) = a0
+    hint = PosLen'
+
+instance Hint PosLen_ where
+    unhint (PosLen_ a0) = a0
+    hint = PosLen_
+
+
+instance Applicative Once where
+    pure p0 = Once p0
+    (<*>) (Once f0) (Once a0) = Once $ f0 a0
+
+
+instance Applicative All where
+    pure p0 = All p0
+    (<*>) (All f0) (All a0) = All $ f0 a0
diff --git a/src/Text/Regex/Do/Type/Regex.hs b/src/Text/Regex/Do/Type/Regex.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Regex/Do/Type/Regex.hs
@@ -0,0 +1,60 @@
+module Text.Regex.Do.Type.Regex
+    (Regex(..),
+    makeRegex',
+    makeRegexOpt',
+    Rx_, Opt_, Ro_) where
+
+import qualified Text.Regex.Base.RegexLike as R
+import qualified Text.Regex.Do.Type.Reexport as R
+import Data.ByteString
+import Text.Regex.Do.Type.Do
+import Text.Regex.Do.Pcre.Option
+
+
+class Regex a where
+   makeRegex::Pattern a -> R.Regex
+   makeRegexOpt::Pattern a -> [Comp] -> [Exec] -> R.Regex
+
+
+makeRegex'::Regex a => Pattern a -> Pattern R.Regex
+makeRegex' = Pattern . makeRegex
+
+makeRegexOpt'::Regex a => Pattern a -> [Comp] -> [Exec] -> Pattern R.Regex
+makeRegexOpt' p0 c0 e0 = Pattern $ makeRegexOpt p0 c0 e0
+
+
+
+instance Regex a => Regex (Utf8_ a) where
+   makeRegex p0 = makeRegexOpt (Pattern val <*> p0) [Utf8] []
+   makeRegexOpt p0 c0 e0 = makeRegexOpt (Pattern val <*> p0) (Utf8:c0) e0
+
+
+instance Regex ByteString where
+   makeRegex (Pattern p0) = R.makeRegex p0
+   makeRegexOpt = makeRegexOpts
+
+
+instance Regex String where
+   makeRegex (Pattern p0) = R.makeRegex p0
+   makeRegexOpt = makeRegexOpts
+
+
+instance Regex R.Regex where
+   makeRegex (Pattern p0) = p0
+   makeRegexOpt (Pattern p0) _ _ = p0
+
+
+-- | tweak Regex with options
+makeRegexOpts::Opt_ a =>
+    Pattern a ->
+        [Comp] -> [Exec] ->
+            R.Regex
+makeRegexOpts (Pattern pat0) comp0 exec0 = rx1
+   where c1 = comp comp0
+         e1 = exec exec0
+         rx1 = R.makeRegexOpts c1 e1 pat0
+
+
+type Rx_ a b = (Regex a, R.Extract b, R.RegexLike R.Regex b)
+type Opt_ a = R.RegexMaker R.Regex R.CompOption R.ExecOption a
+type Ro_ rx = (Regex rx, Opt_ rx)
diff --git a/src/Text/Regex/Do/Type/Regex_.hs b/src/Text/Regex/Do/Type/Regex_.hs
deleted file mode 100644
--- a/src/Text/Regex/Do/Type/Regex_.hs
+++ /dev/null
@@ -1,40 +0,0 @@
-module Text.Regex.Do.Type.Regex_ where
-
-import qualified Text.Regex.Base.RegexLike as R
-import Text.Regex.Do.Type.Reexport
-import Data.ByteString
-import Text.Regex.Do.Type.Do
-import Text.Regex.Do.Pcre.Option
-
-
-class Regex_ a where
-   r_::Pattern a -> Regex
-   ropt_::Pattern a -> [Comp] -> [Exec] -> Regex
-
-
-instance Regex_ ByteString where
-   r_ (Pattern p0) = R.makeRegex p0
-   ropt_ = makeRegexOpts
-
-instance Regex_ String where
-   r_ (Pattern p0) = R.makeRegex p0
-   ropt_ = makeRegexOpts
-
-instance Regex_ Regex where
-   r_ (Pattern p0) = p0
-   ropt_ (Pattern p0) _ _ = p0
-
-
-type Rx_ a b = (Regex_ a, R.Extract b, R.RegexLike Regex b)
-type Opt_ a = R.RegexMaker Regex CompOption ExecOption a
-
-
--- | tweak Regex with options
-makeRegexOpts::Opt_ a =>
-    Pattern a ->
-        [Comp] -> [Exec] ->
-            Regex
-makeRegexOpts (Pattern pat0) comp0 exec0 = rx1
-   where c1 = comp comp0
-         e1 = exec exec0
-         rx1 = R.makeRegexOpts c1 e1 pat0
diff --git a/test/Main.hs b/test/Main.hs
--- a/test/Main.hs
+++ b/test/Main.hs
@@ -3,17 +3,18 @@
 import qualified TestRegex.TestFormat as F
 import qualified TestRegex.TestPcre as P
 import qualified TestRegex.TestReplace as R
+import qualified TestRegex.TestReplaceUtf as U
 import qualified TestRegex.TestReplaceOpen as O
 import qualified TestRegex.TestSplit as S
 import qualified TestRegex.TestTrim as T
 
 
-
 main::IO()
 main = do
             F.main
             P.main
-            R.main
             S.main
             T.main
             O.main
+            R.main
+            U.main
diff --git a/test/TestRegex/TestPcre.hs b/test/TestRegex/TestPcre.hs
--- a/test/TestRegex/TestPcre.hs
+++ b/test/TestRegex/TestPcre.hs
@@ -2,11 +2,14 @@
 
 import Test.Hspec
 import Text.Regex.Do.Type.Do as M
-import Text.Regex.Do.Pcre.Match as M
+import Text.Regex.Do.Pcre.Ascii.Match as M
+import Text.Regex.Do.Pcre.Utf8.Match as U
+import Text.Regex.Do.Pcre.Ascii.MatchHint as S
+import Text.Regex.Do.Pcre.Utf8.MatchHint as Su
 import Text.Regex.Do.Convert
 import Data.ByteString
-import Text.Regex.Do.Pcre.MatchHint as S
 import Text.Regex.Do.Type.MatchHint as S
+import Text.Regex.Do.Type.Regex
 
 
 main::IO()
@@ -20,10 +23,23 @@
      it " cd " $ S.match (PosLen' $ Pattern ("^cd"::String)) (Body "abcde") `shouldBe` []
      it " ab " $ S.match (Test $ Pattern ("^ab"::String)) (Body "abc") `shouldBe` True
      it "doc 1" $ Test ("в"::ByteString) S.=~ "тихо в лесу" `shouldBe` True
+     it "doc 1" $ Test (toByteString "в") Su.=~ toByteString "тихо в лесу" `shouldBe` True
      it "doc 2" $ S.Once ("^all"::String) S.=~ "all the time" `shouldBe` ["all"]
      it "doc 3" $ S.Once ("^all"::ByteString) S.=~ "all the time" `shouldBe` ["all"]
      it "doc 4" $ S.All ("well"::ByteString) S.=~ "all is well that ends well" `shouldBe` ([["well"],["well"]])
      it "doc 5" $ PosLen' ("и"::String) S.=~ "бывает и хуже" `shouldBe` [(13,2)]
+     it "doc 6" $ PosLen' ("à"::String) S.=~ "tourner à gauche" `shouldBe` [(8,2)]
+     it "doc 7" $ do
+        let rx1 = makeRegexOpt' (Pattern $ toByteString'"左") [] []
+            rx2 = Utf8_ <$> rx1
+            m1 = U.match rx2 (Body $ toByteString' "100メートル左折後、左")::[ByteString]
+        m1 `shouldBe` [toByteString "左"]
+     it "doc 8" $ do
+        let t1 = toByteString "в" U.=~ ("тихо в лесу"::String)::Bool
+        t1 `shouldBe` True
+     it "doc 9" $ do
+        let m1 = ("well"::String) U.=~ ("all is well that ends well"::String)::[[String]]
+        m1 `shouldBe` ([["well"],["well"]]::[[String]])
 
 n = "d1"
 h = Body "abcd1efg d1hij"
diff --git a/test/TestRegex/TestReplace.hs b/test/TestRegex/TestReplace.hs
--- a/test/TestRegex/TestReplace.hs
+++ b/test/TestRegex/TestReplace.hs
@@ -4,13 +4,14 @@
 import Test.Hspec
 import Text.Regex.Do.Type.Do
 
-import Text.Regex.Do.Pcre.Replace as R
-import Text.Regex.Do.Pcre.ReplaceOpen hiding (replace)
+import Text.Regex.Do.Pcre.Ascii.Replace as R
+import qualified Text.Regex.Do.Pcre.Utf8.Replace as U
+import Text.Regex.Do.ReplaceOpen hiding (replace)
 import Text.Regex.Do.Convert
 import Data.ByteString as B
 import Debug.Trace
 import Text.Regex.Do.Type.MatchHint
-import Text.Regex.Do.Pcre.Option
+--import Text.Regex.Do.Pcre.Option
 
 main::IO()
 main = do
@@ -24,19 +25,19 @@
 doc = hspec $ do
        describe "Pcre.Replace doc" $ do
           it "replaceGroup 1" $ do
-            replace (Once []) (Pattern "\\w=(\\d{1,3})") replacer (Body "a=101 b=3 12")
+            replace (Once (Pattern "\\w=(\\d{1,3})")) replacer (Body "a=101 b=3 12")
                 `shouldBe` "a=[сто один] b=3 12"
           it "replaceGroup 2" $ do
-            replace (All []) (Pattern "\\w=(\\d{1,3})") replacer (Body "a=101 b=3 12")
+            replace (All (Pattern "\\w=(\\d{1,3})")) replacer (Body "a=101 b=3 12")
                 `shouldBe` "a=[сто один] b=[three] 12"
           it "replace 3" $ do
-            replace (Once [Utf8]) (Pattern "менее") (Replacement  "более") (Body "менее менее")
+            U.replace (Once (Pattern $ Utf8_ "менее")) (Replacement $ Utf8_ $ "более") (Body $ Utf8_ "менее менее")
                 `shouldBe` "более менее"
           it "replace 4" $ do
-            replace (All[Utf8]) (Pattern "менее") (Replacement  "боле") (Body "менее менее")
+            U.replace (All (Pattern $ Utf8_ "менее")) (Replacement $ Utf8_ $ "боле") (Body $ Utf8_ "менее менее")
                 `shouldBe` "боле боле"
           it "replace 5" $ do
-            replace (Once[]) (Pattern "^a\\s") (Replacement "A") (Body "a bc хол.гор.")
+            replace (Once (Pattern "^a\\s")) (Replacement "A") (Body "a bc хол.гор.")
                 `shouldBe` "Abc хол.гор."
 
 
@@ -44,9 +45,9 @@
 onceUtf8 = hspec $ do
        describe "Pcre.Replace Once Utf8" $ do
           it "^a\\s" $ do
-            replace (Once[]) (Pattern "^a\\s") (Replacement "A") (Body "a bc хол.гор.") `shouldBe` "Abc хол.гор."
+            replace (Once (Pattern "^a\\s")) (Replacement "A") (Body "a bc хол.гор.") `shouldBe` "Abc хол.гор."
           it "^b\\s" $ do
-            replace (Once[]) (Pattern "^b\\s") (Replacement "A") (Body "a bc хол.гор.") `shouldBe` "a bc хол.гор."
+            replace (Once (Pattern "^b\\s")) (Replacement "A") (Body "a bc хол.гор.") `shouldBe` "a bc хол.гор."
 
 
 latinOnceAll::IO()
@@ -61,7 +62,7 @@
                            body1 = Body $ toByteString haystack1
                            haystack1 = "a=10 b=11 12"
                            repl1  = replacement "text1"
-                     in replace (hint1 []) rx1 repl1 body1
+                     in replace (hint1 rx1) repl1 body1
 
 
 pattern::String -> Pattern ByteString
@@ -76,13 +77,13 @@
 groupReplace =  hspec $ do
          describe "Pcre.Replace group" $ do
             it "Once" $ do
-               runFn1 (Once[Utf8]) `shouldBe` "a=[сто один] b=3 12"
+               runFn1 Once `shouldBe` "a=[сто один] b=3 12"
             it "All" $ do
-               runFn1 (All[Utf8]) `shouldBe` "a=[сто один] b=[three] 12"
+               runFn1 All `shouldBe` "a=[сто один] b=[three] 12"
             where runFn1 opts1 =
                      let   rx1 = Pattern "\\w=(\\d{1,3})"
                            body1 = Body "a=101 b=3 12"
-                     in replace opts1 rx1 replacer body1
+                     in replace (opts1 rx1) replacer body1
 
 
 replacer::GroupReplacer String
diff --git a/test/TestRegex/TestReplaceOpen.hs b/test/TestRegex/TestReplaceOpen.hs
--- a/test/TestRegex/TestReplaceOpen.hs
+++ b/test/TestRegex/TestReplaceOpen.hs
@@ -2,7 +2,7 @@
 module TestRegex.TestReplaceOpen where
 
 import Test.Hspec
-import Text.Regex.Do.Pcre.ReplaceOpen as O
+import Text.Regex.Do.ReplaceOpen as O
 import Text.Regex.Do.Type.Do
 import Data.Text
 import Text.Regex.Do.Convert()
diff --git a/test/TestRegex/TestReplaceUtf.hs b/test/TestRegex/TestReplaceUtf.hs
new file mode 100644
--- /dev/null
+++ b/test/TestRegex/TestReplaceUtf.hs
@@ -0,0 +1,31 @@
+module TestRegex.TestReplaceUtf where
+
+import Test.Hspec
+import Text.Regex.Do.Type.Do
+import Data.ByteString
+import Text.Regex.Do.Convert
+import Text.Regex.Do.Pcre.Utf8.Replace as U
+import Text.Regex.Do.Type.MatchHint
+import Text.Regex.Do.ReplaceOpen
+
+
+main::IO()
+main = groupReplace
+
+groupReplace::IO()
+groupReplace =  hspec $ do
+       describe "TestRegex.TestReplaceUtf" $ do
+            it "All" $ do
+               runFn1 `shouldBe` toByteString "100メートルー右ー折後、左"
+            where runFn1 =
+                     let rx1 = Pattern $ toByteString' "(?<=ル)(左)"
+                         body1 = Body $ toByteString' "100メートル左折後、左"
+                     in U.replace (All rx1) replacer body1
+
+
+replacer::GroupReplacer (Utf8_ ByteString)
+replacer = defaultReplacer 1 tweak1
+      where tweak1 bs1 = toByteString' $
+                            if bs1 == toByteString' "左" then
+                                  "ー右ー"
+                                  else "?"
diff --git a/test/TestRegex/TestSplit.hs b/test/TestRegex/TestSplit.hs
--- a/test/TestRegex/TestSplit.hs
+++ b/test/TestRegex/TestSplit.hs
@@ -36,19 +36,19 @@
 
        describe "StringSearch.Search zerolength" $ do
           it "break" $ do
-            evaluate (errFn $ break Drop) `shouldThrow` anyException
+            evaluate (errFn1 $ break Drop) `shouldThrow` anyException
           it "break front" $ do
-            evaluate (errFn $ break Front) `shouldThrow` anyException
+            evaluate (errFn1 $ break Front) `shouldThrow` anyException
           it "break end" $ do
-            evaluate (errFn $ break End) `shouldThrow` anyException
+            evaluate (errFn1 $ break End) `shouldThrow` anyException
           it "replace" $ do
             evaluate (S.replace (Pattern B.empty) with body) `shouldThrow` anyException
           it "split" $ do
-            evaluate (errFn $ split Drop) `shouldThrow` anyException
+            evaluate (errFn2 $ split Drop) `shouldThrow` anyException
           it "split end" $ do
-            evaluate (errFn $ split End) `shouldThrow` anyException
+            evaluate (errFn2 $ split End) `shouldThrow` anyException
           it "split front" $ do
-            evaluate (errFn $ split Front) `shouldThrow` anyException
+            evaluate (errFn2 $ split Front) `shouldThrow` anyException
 
        describe "StringSearch.Search break delim not found" $ do
             it "delim not found" $ do
@@ -67,7 +67,8 @@
                split_sp1 = split Drop pat_sp body_sp
                splitFront1 = split Front pat body
                splitEnd1 = split End pat body
-               errFn fn1 = fn1 (Pattern B.empty) body
+               errFn1 fn1 = fn1 (Pattern B.empty) body
+               errFn2 fn1 = fn1 (Pattern B.empty) body
                b = toByteString
                --   break delim not found
                pat_nf = Pattern ":"
