diff --git a/Data/Monoid/Factorial.hs b/Data/Monoid/Factorial.hs
--- a/Data/Monoid/Factorial.hs
+++ b/Data/Monoid/Factorial.hs
@@ -126,10 +126,10 @@
    foldr f f0 = List.foldr f f0 . factors
    length = List.length . factors
    map f = foldr (mappend . f) mempty
-   span p = foldr f (mempty, mempty)
-      where f s (prefix, suffix) = if p s 
-                                   then (mappend s prefix, suffix) 
-                                   else (mempty, mappend s (mappend prefix suffix))
+   span p m = spanAfter id m
+      where spanAfter f m = case splitPrimePrefix m
+                            of Just (prime, rest) | p prime -> spanAfter (f . mappend prime) rest
+                               _ -> (f mempty, m)
    break = span . (not .)
    split p m = foldr f [mempty] m
       where f prime s@(x:xs) | p prime = mempty : s 
diff --git a/Data/Monoid/Instances/ByteString/UTF8.hs b/Data/Monoid/Instances/ByteString/UTF8.hs
--- a/Data/Monoid/Instances/ByteString/UTF8.hs
+++ b/Data/Monoid/Instances/ByteString/UTF8.hs
@@ -20,6 +20,8 @@
 import Data.String (IsString(fromString))
 import Data.ByteString (ByteString)
 import qualified Data.ByteString as ByteString
+import qualified Data.ByteString.Char8 as ByteString.Char8
+import Data.ByteString.Unsafe (unsafeDrop, unsafeIndex)
 import qualified Data.ByteString.UTF8 as UTF8
 
 import Data.Monoid (Monoid)
@@ -27,10 +29,15 @@
 import Data.Monoid.Null (MonoidNull)
 import Data.Monoid.Factorial (FactorialMonoid(..))
 import Data.Monoid.Textual (TextualMonoid(..))
+import qualified Data.Monoid.Factorial as Factorial (FactorialMonoid(..))
+import qualified Data.Monoid.Textual as Textual (TextualMonoid(..))
 
-newtype ByteStringUTF8 = ByteStringUTF8 ByteString deriving (Eq, Show, Monoid, MonoidNull,
+newtype ByteStringUTF8 = ByteStringUTF8 ByteString deriving (Eq, Monoid, MonoidNull,
                                                              LeftReductiveMonoid, LeftCancellativeMonoid, LeftGCDMonoid)
 
+instance Show ByteStringUTF8 where
+   show (ByteStringUTF8 bs) = show (UTF8.toString bs)
+
 instance IsString ByteStringUTF8 where
    fromString = ByteStringUTF8 . UTF8.fromString
 
@@ -43,12 +50,43 @@
    take n (ByteStringUTF8 bs) = ByteStringUTF8 (UTF8.take n bs)
    drop n (ByteStringUTF8 bs) = ByteStringUTF8 (UTF8.drop n bs)
    length (ByteStringUTF8 bs) = UTF8.length bs
+   span p (ByteStringUTF8 bs) = wrapPair (loop 0)
+      where limit = ByteString.length bs
+            loop i = if i < limit
+                     then let w = unsafeIndex bs i
+                          in if w < 0x80
+                             then if p (ByteStringUTF8 $ ByteString.singleton w)
+                                  then loop (succ i)
+                                  else ByteString.splitAt i bs
+                             else let cs = ByteString.drop i bs
+                                  in case UTF8.decode cs
+                                     of Just (_,n) | p (ByteStringUTF8 $ ByteString.take n cs)
+                                                     -> loop (i+n)
+                                        _ -> ByteString.splitAt i bs
+                     else (bs, ByteString.empty)
+   break p = Factorial.span (not . p)
+   takeWhile p = fst . Factorial.span p
+   dropWhile p = snd . Factorial.span p
 
 instance TextualMonoid ByteStringUTF8 where
    splitCharacterPrefix (ByteStringUTF8 bs) = do (c, rest) <- UTF8.uncons bs
                                                  if c == UTF8.replacement_char
                                                     then Nothing
                                                     else return (c, ByteStringUTF8 rest)
-
+   span pb pc (ByteStringUTF8 bs) = wrapPair (spanASCII 0 bs)
+      where spanASCII i rest = case ByteString.Char8.findIndex (\c-> c > '\x7f' || not (pc c)) rest
+                               of Nothing -> (bs, ByteString.empty)
+                                  Just j -> if unsafeIndex rest j > 0x7f
+                                            then spanMultiByte (i + j) (unsafeDrop j rest)
+                                            else ByteString.splitAt (i + j) bs
+            spanMultiByte i rest = case UTF8.decode rest
+                                   of Just (c,n) | if c == UTF8.replacement_char
+                                                      then pb (ByteStringUTF8 $ ByteString.take n rest)
+                                                      else pc c
+                                                   -> spanASCII (i+n) (unsafeDrop n rest)
+                                      _ -> ByteString.splitAt i bs
+   break pb pc = Textual.span (not . pb) (not . pc)
+   takeWhile pb pc = fst . Textual.span pb pc
+   dropWhile pb pc = snd . Textual.span pb pc
 
 wrapPair (bs1, bs2) = (ByteStringUTF8 bs1, ByteStringUTF8 bs2)
diff --git a/monoid-subclasses.cabal b/monoid-subclasses.cabal
--- a/monoid-subclasses.cabal
+++ b/monoid-subclasses.cabal
@@ -1,5 +1,5 @@
 Name:                monoid-subclasses
-Version:             0.1.1
+Version:             0.1.2
 Cabal-Version:       >= 1.10
 Build-Type:          Simple
 Synopsis:            Subclasses of Monoid
